home *** CD-ROM | disk | FTP | other *** search
/ Freelog 70 / Freelog070.iso / Internet / EasyPHP / easyphp1-8_setup.exe / {app} / phpmyadmin / libraries / common.lib.php < prev    next >
Encoding:
PHP Script  |  2005-01-16  |  96.1 KB  |  2,496 lines

  1. <?php
  2. /* $Id: common.lib.php,v 2.111.2.1 2005/01/16 14:37:30 lem9 Exp $ */
  3. // vim: expandtab sw=4 ts=4 sts=4:
  4.  
  5. /**
  6.  * Misc stuff and functions used by almost all the scripts.
  7.  * Among other things, it contains the advanced authentification work.
  8.  */
  9.  
  10. /**
  11.  * Order of sections for common.lib.php:
  12.  *
  13.  * some functions need the constants of libraries/defines.lib.php
  14.  * and defines_mysql.lib.php
  15.  *
  16.  * the PMA_setFontSizes() function must be before the call to the
  17.  * libraries/auth/cookie.auth.lib.php library
  18.  *
  19.  * the include of libraries/defines_mysql.lib.php must be after the connection
  20.  * to db to get the MySql version
  21.  *
  22.  * the PMA_sqlAddslashes() function must be before the connection to db
  23.  *
  24.  * the authentication libraries must be before the connection to db but
  25.  * after the PMA_isInto() function
  26.  *
  27.  * the PMA_mysqlDie() function must be before the connection to db but
  28.  * after mysql extension has been loaded
  29.  *
  30.  * the PMA_mysqlDie() function needs the PMA_format_sql() Function
  31.  *
  32.  * ... so the required order is:
  33.  *
  34.  * - parsing of the configuration file
  35.  * - load of the libraries/defines.lib.php library
  36.  * - load of mysql extension (if necessary)
  37.  * - definition of PMA_sqlAddslashes()
  38.  * - definition of PMA_format_sql()
  39.  * - definition of PMA_mysqlDie()
  40.  * - definition of PMA_isInto()
  41.  * - definition of PMA_setFontSizes()
  42.  * - loading of an authentication library
  43.  * - db connection
  44.  * - authentication work
  45.  * - load of the libraries/defines_mysql.lib.php library to get the MySQL
  46.  *   release number
  47.  * - other functions, respecting dependencies
  48.  */
  49.  
  50. /**
  51.  * Minimum inclusion? (i.e. for the stylesheet builder)
  52.  */
  53.  
  54. if (!isset($is_minimum_common)) {
  55.     $is_minimum_common = FALSE;
  56. }
  57.  
  58. /**
  59.  * Avoids undefined variables
  60.  */
  61. if (!isset($use_backquotes)) {
  62.     $use_backquotes   = 0;
  63. }
  64. if (!isset($pos)) {
  65.     $pos              = 0;
  66. }
  67.  
  68. /**
  69.  * 2004-06-30 rabus: Ensure, that $cfg variables are not set somwhere else
  70.  * before including the config file.
  71.  */
  72. unset($cfg);
  73.  
  74. /**
  75.  * Detects the config file we want to load
  76.  */
  77. if (file_exists('./config.inc.developer.php')) {
  78.     $cfgfile_to_load = './config.inc.developer.php';
  79. } else {
  80.     $cfgfile_to_load = './config.inc.php';
  81. }
  82.  
  83. /**
  84.  * Parses the configuration file and gets some constants used to define
  85.  * versions of phpMyAdmin/php/mysql...
  86.  */
  87. $old_error_reporting = error_reporting(0);
  88. include_once($cfgfile_to_load);
  89. // Include failed
  90. if (!isset($cfgServers) && !isset($cfg['Servers'])) {
  91.     // Creates fake settings
  92.     $cfg = array('DefaultLang'           => 'en-iso-8859-1',
  93.                     'AllowAnywhereRecoding' => FALSE);
  94.     // Loads the language file
  95.     require_once('./libraries/select_lang.lib.php');
  96.     // Sends the Content-Type header
  97.     header('Content-Type: text/html; charset=' . $charset);
  98.     // Displays the error message
  99.     ?>
  100. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  101. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  102. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $available_languages[$lang][2]; ?>" lang="<?php echo $available_languages[$lang][2]; ?>" dir="<?php echo $text_dir; ?>">
  103.  
  104. <head>
  105. <title>phpMyAdmin</title>
  106. <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $charset; ?>" />
  107.  
  108. <style type="text/css">
  109. <!--
  110. body  {font-family: sans-serif; font-size: small; color: #000000; background-color: #F5F5F5}
  111. h1    {font-family: sans-serif; font-size: large; font-weight: bold}
  112. //-->
  113. </style>
  114. </head>
  115.  
  116.  
  117. <body bgcolor="#ffffff">
  118. <h1>phpMyAdmin - <?php echo $strError; ?></h1>
  119. <p>
  120. <?php echo $strConfigFileError; ?><br /><br />
  121. <a href="config.inc.php" target="_blank">config.inc.php</a>
  122. </p>
  123. </body>
  124.  
  125. </html>
  126.     <?php
  127.     exit();
  128. }
  129. error_reporting($old_error_reporting);
  130. unset($old_error_reporting, $cfgfile_to_load);
  131.  
  132. /**
  133.  * Includes compatibility code for older config.inc.php revisions
  134.  * if necessary
  135.  */
  136. if (isset($cfg['FileRevision'])) {
  137.     // converting revision string into an array
  138.     //     e.g. "Revision: 2.0" becomes array(2, 0).
  139.     $cfg['FileRevision'] = str_replace('$' . 'Revision: ', '', $cfg['FileRevision']);
  140.     $cfg['FileRevision'] = str_replace(' $', '', $cfg['FileRevision']);
  141.     $cfg['FileRevision'] = explode('.', $cfg['FileRevision']);
  142. } else {
  143.     $cfg['FileRevision'] = array(1, 1);
  144. }
  145. if ($cfg['FileRevision'][0] < 2 || ($cfg['FileRevision'][0] == 2 && $cfg['FileRevision'][1] < 48)) {
  146.     require_once('./libraries/config_import.lib.php');
  147. }
  148.  
  149. /**
  150.  * Includes the language file if it hasn't been included yet
  151.  */
  152. require_once('./libraries/select_lang.lib.php');
  153. /**
  154.  * Gets constants that defines the PHP version number.
  155.  * This include must be located physically before any code that needs to
  156.  * reference the constants, else PHP 3.0.16 won't be happy.
  157.  */
  158. require_once('./libraries/defines.lib.php');
  159.  
  160. if ($is_minimum_common == FALSE) {
  161.     /**
  162.      * Define $is_upload
  163.      */
  164.  
  165.       $is_upload = TRUE;
  166.       if (strtolower(@ini_get('file_uploads')) == 'off'
  167.              || @ini_get('file_uploads') == 0) {
  168.           $is_upload = FALSE;
  169.       }
  170.  
  171.     /**
  172.      * Maximum upload size as limited by PHP
  173.      * Used with permission from Moodle (http://moodle.org) by Martin Dougiamas
  174.      *
  175.      * this section generates $max_upload_size in bytes
  176.      */
  177.  
  178.     function get_real_size($size=0) {
  179.     /// Converts numbers like 10M into bytes
  180.         if (!$size) {
  181.             return 0;
  182.         }
  183.         $scan['MB'] = 1048576;
  184.         $scan['Mb'] = 1048576;
  185.         $scan['M'] = 1048576;
  186.         $scan['m'] = 1048576;
  187.         $scan['KB'] = 1024;
  188.         $scan['Kb'] = 1024;
  189.         $scan['K'] = 1024;
  190.         $scan['k'] = 1024;
  191.  
  192.         while (list($key) = each($scan)) {
  193.             if ((strlen($size)>strlen($key))&&(substr($size, strlen($size) - strlen($key))==$key)) {
  194.                 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
  195.                 break;
  196.             }
  197.         }
  198.         return $size;
  199.     } // end function
  200.  
  201.  
  202.     if (!$filesize = ini_get('upload_max_filesize')) {
  203.         $filesize = "5M";
  204.     }
  205.     $max_upload_size = get_real_size($filesize);
  206.  
  207.     if ($postsize = ini_get('post_max_size')) {
  208.         $postsize = get_real_size($postsize);
  209.         if ($postsize < $max_upload_size) {
  210.             $max_upload_size = $postsize;
  211.         }
  212.     }
  213.     unset($filesize);
  214.     unset($postsize);
  215.  
  216.     /**
  217.      * other functions for maximum upload work
  218.      */
  219.  
  220.     /**
  221.      * Displays the maximum size for an upload
  222.      *
  223.      * @param   integer  the size
  224.      *
  225.      * @return  string   the message
  226.      *
  227.      * @access  public
  228.      */
  229.      function PMA_displayMaximumUploadSize($max_upload_size) {
  230.          list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);
  231.          return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
  232.      }
  233.  
  234.     /**
  235.      * Generates a hidden field which should indicate to the browser
  236.      * the maximum size for upload
  237.      *
  238.      * @param   integer  the size
  239.      *
  240.      * @return  string   the INPUT field
  241.      *
  242.      * @access  public
  243.      */
  244.      function PMA_generateHiddenMaxFileSize($max_size){
  245.          return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
  246.      }
  247.  
  248.     /**
  249.      * Charset conversion.
  250.      */
  251.     require_once('./libraries/charset_conversion.lib.php');
  252.  
  253.     /**
  254.      * String handling
  255.      */
  256.     require_once('./libraries/string.lib.php');
  257. }
  258.  
  259. /**
  260.  * Removes insecure parts in a path; used before include() or
  261.  * require() when a part of the path comes from an insecure source
  262.  * like a cookie or form.
  263.  *
  264.  * @param    string  The path to check
  265.  *
  266.  * @return   string  The secured path
  267.  *
  268.  * @access  public
  269.  * @author  Marc Delisle (lem9@users.sourceforge.net)
  270.  */
  271. function PMA_securePath($path) {
  272.  
  273.     // change .. to .
  274.     $path = preg_replace('@\.\.*@','.',$path);
  275.  
  276.     return $path;
  277. } // end function
  278.  
  279. // If zlib output compression is set in the php configuration file, no
  280. // output buffering should be run
  281. if (@ini_get('zlib.output_compression')) {
  282.     $cfg['OBGzip'] = FALSE;
  283. }
  284.  
  285. // disable output-buffering (if set to 'auto') for IE6, else enable it.
  286. if (strtolower($cfg['OBGzip']) == 'auto') {
  287.     if (PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER >= 6 && PMA_USR_BROWSER_VER < 7) {
  288.         $cfg['OBGzip'] = FALSE;
  289.     } else {
  290.         $cfg['OBGzip'] = TRUE;
  291.     }
  292. }
  293.  
  294.  
  295. /* Theme Manager
  296.  * 2004-05-20 Michael Keck (mail_at_michaelkeck_dot_de)
  297.  *            This little script checks if there're themes available
  298.  *            and if the directory $ThemePath/$theme/img/ exists
  299.  *            If not, it will use default images
  300. */
  301. // Theme Manager
  302. if (!$cfg['ThemeManager'] || !isset($_COOKIE['pma_theme']) || empty($_COOKIE['pma_theme'])){
  303.     $GLOBALS['theme'] = $cfg['ThemeDefault'];
  304.     $ThemeDefaultOk = FALSE;
  305.     if ($cfg['ThemePath']!='' && $cfg['ThemePath'] != FALSE) {
  306.         $tmp_theme_mainpath = $cfg['ThemePath'];
  307.         $tmp_theme_fullpath = $cfg['ThemePath'] . '/' .$cfg['ThemeDefault'];
  308.         if (@is_dir($tmp_theme_mainpath)) {
  309.             if (isset($cfg['ThemeDefault']) && @is_dir($tmp_theme_fullpath)) {
  310.                 $ThemeDefaultOk = TRUE;
  311.             }
  312.         }
  313.     }
  314.     if ($ThemeDefaultOk == TRUE){
  315.         $GLOBALS['theme'] = $cfg['ThemeDefault'];
  316.     } else {
  317.         $GLOBALS['theme'] = 'original';
  318.     }
  319. } else {
  320.     // if we just changed theme, we must take the new one so that
  321.     // index.php takes the correct one for height computing
  322.     if (isset($_POST['set_theme'])) {
  323.         $GLOBALS['theme'] = PMA_securePath($_POST['set_theme']);
  324.     } else {
  325.         $GLOBALS['theme'] = PMA_securePath($_COOKIE['pma_theme']);
  326.     }
  327. }
  328.  
  329. // check for theme requires/name
  330. unset($theme_name, $theme_generation, $theme_version);
  331. @include($cfg['ThemePath'] . '/' . $GLOBALS['theme'] . '/info.inc.php');
  332.  
  333. // did it set correctly?
  334. if (!isset($theme_name, $theme_generation, $theme_version))
  335.     $GLOBALS['theme'] = 'original'; // invalid theme
  336.  
  337. if ($theme_generation != PMA_THEME_GENERATION)
  338.     $GLOBALS['theme'] = 'original'; // different generation
  339.  
  340. if ($theme_version < PMA_THEME_VERSION)
  341.     $GLOBALS['theme'] = 'original'; // too old version
  342.  
  343. $pmaThemeImage  = $cfg['ThemePath'] . '/' . $GLOBALS['theme'] . '/img/';
  344. $tmp_layout_file = $cfg['ThemePath'] . '/' . $GLOBALS['theme'] . '/layout.inc.php';
  345. if (@file_exists($tmp_layout_file)) {
  346.     include($tmp_layout_file);
  347. }
  348. if (!is_dir($pmaThemeImage)) {
  349.     $pmaThemeImage = $cfg['ThemePath'] . '/original/img/';
  350. }
  351. // end theme manager
  352.  
  353. /**
  354.  * collation_connection
  355.  */
  356.  // (could be improved by executing it after the MySQL connection only if
  357.  //  PMA_MYSQL_INT_VERSION >= 40100 )
  358. if (isset($_COOKIE) && !empty($_COOKIE['pma_collation_connection']) && empty($_POST['collation_connection'])) {
  359.     $collation_connection = $_COOKIE['pma_collation_connection'];
  360. }
  361.  
  362.  
  363. if ($is_minimum_common == FALSE) {
  364.     /**
  365.      * Include URL/hidden inputs generating.
  366.      */
  367.     require_once('./libraries/url_generating.lib.php');
  368.  
  369.     /**
  370.      * Add slashes before "'" and "\" characters so a value containing them can
  371.      * be used in a sql comparison.
  372.      *
  373.      * @param   string   the string to slash
  374.      * @param   boolean  whether the string will be used in a 'LIKE' clause
  375.      *                   (it then requires two more escaped sequences) or not
  376.      * @param   boolean  whether to treat cr/lfs as escape-worthy entities
  377.      *                   (converts \n to \\n, \r to \\r)
  378.      *
  379.      * @return  string   the slashed string
  380.      *
  381.      * @access  public
  382.      */
  383.     function PMA_sqlAddslashes($a_string = '', $is_like = FALSE, $crlf = FALSE)
  384.     {
  385.         if ($is_like) {
  386.             $a_string = str_replace('\\', '\\\\\\\\', $a_string);
  387.         } else {
  388.             $a_string = str_replace('\\', '\\\\', $a_string);
  389.         }
  390.  
  391.         if ($crlf) {
  392.             $a_string = str_replace("\n", '\n', $a_string);
  393.             $a_string = str_replace("\r", '\r', $a_string);
  394.             $a_string = str_replace("\t", '\t', $a_string);
  395.         }
  396.  
  397.         $a_string = str_replace('\'', '\'\'', $a_string);
  398.  
  399.         return $a_string;
  400.     } // end of the 'PMA_sqlAddslashes()' function
  401.  
  402.  
  403.     /**
  404.      * Add slashes before "_" and "%" characters for using them in MySQL
  405.      * database, table and field names.
  406.      * Note: This function does not escape backslashes!
  407.      *
  408.      * @param   string   the string to escape
  409.      *
  410.      * @return  string   the escaped string
  411.      *
  412.      * @access  public
  413.      */
  414.     function PMA_escape_mysql_wildcards($name)
  415.     {
  416.         $name = str_replace('_', '\\_', $name);
  417.         $name = str_replace('%', '\\%', $name);
  418.  
  419.         return $name;
  420.     } // end of the 'PMA_escape_mysql_wildcards()' function
  421.  
  422.  
  423.     /**
  424.      * format sql strings
  425.      *
  426.      * @param   mixed    pre-parsed SQL structure
  427.      *
  428.      * @return  string   the formatted sql
  429.      *
  430.      * @global  array    the configuration array
  431.      * @global  boolean  whether the current statement is a multiple one or not
  432.      *
  433.      * @access  public
  434.      *
  435.      * @author  Robin Johnson <robbat2@users.sourceforge.net>
  436.      */
  437.     function PMA_formatSql($parsed_sql, $unparsed_sql = '')
  438.     {
  439.         global $cfg;
  440.  
  441.         // Check that we actually have a valid set of parsed data
  442.         // well, not quite
  443.         // first check for the SQL parser having hit an error
  444.         if (PMA_SQP_isError()) {
  445.             return $parsed_sql;
  446.         }
  447.         // then check for an array
  448.         if (!is_array($parsed_sql)) {
  449.             // We don't so just return the input directly
  450.             // This is intended to be used for when the SQL Parser is turned off
  451.             $formatted_sql = '<pre>' . "\n"
  452.                             . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
  453.                             . '</pre>';
  454.             return $formatted_sql;
  455.         }
  456.  
  457.         $formatted_sql        = '';
  458.  
  459.         switch ($cfg['SQP']['fmtType']) {
  460.             case 'none':
  461.                 if ($unparsed_sql != '') {
  462.                     $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
  463.                 } else {
  464.                     $formatted_sql = PMA_SQP_formatNone($parsed_sql);
  465.                 }
  466.                 break;
  467.             case 'html':
  468.                 $formatted_sql = PMA_SQP_formatHtml($parsed_sql,'color');
  469.                 break;
  470.             case 'text':
  471.                 //$formatted_sql = PMA_SQP_formatText($parsed_sql);
  472.                 $formatted_sql = PMA_SQP_formatHtml($parsed_sql,'text');
  473.                 break;
  474.             default:
  475.                 break;
  476.         } // end switch
  477.  
  478.         return $formatted_sql;
  479.     } // end of the "PMA_formatSql()" function
  480.  
  481.  
  482.     /**
  483.      * Displays a link to the official MySQL documentation
  484.      *
  485.      * @param   chapter of "HTML, one page per chapter" documentation
  486.      * @param   contains name of page/anchor that is being linked
  487.      *
  488.      * @return  string  the html link
  489.      *
  490.      * @access  public
  491.      */
  492. // 2004-05-04: replaced with a modified function from Michael Keck (mkkeck)
  493.         function PMA_showMySQLDocu($chapter, $link)
  494.         {
  495.  
  496.             if (!empty($GLOBALS['cfg']['MySQLManualBase'])) {
  497.                 if (!empty($GLOBALS['cfg']['MySQLManualType'])) {
  498.                     switch ($GLOBALS['cfg']['MySQLManualType']) {
  499.                         case 'old':
  500.                             if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  501.                                 return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  502.                             }else{
  503.                                 return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  504.                            }
  505.                         case 'chapters':
  506.                             if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  507.                                 return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/manual_' . $chapter . '.html#' . $link . '" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  508.                            } else {
  509.                                return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/manual_' . $chapter . '.html#' . $link . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]'; }
  510.                         case 'big':
  511.                             if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  512.                                 return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '#' . $link . '" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  513.                             } else {
  514.                                 return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '#' . $link . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  515.                             }
  516.                         case 'none':
  517.                             return '';
  518.                         case 'searchable':
  519.                         default:
  520.                             if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  521.                                 return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link . '.html" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  522.                             } else {
  523.                                 return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link . '.html" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  524.                             }
  525.                     }
  526.                 } else {
  527.                     // no Type defined, show the old one
  528.                     if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  529.                         return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  530.                     } else {
  531.                         return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  532.                     }
  533.                 }
  534.             } else {
  535.                 // no URL defined
  536.                 if (!empty($GLOBALS['cfg']['ManualBaseShort'])) {
  537.                     // the old configuration
  538.                     if ($GLOBALS['cfg']['ReplaceHelpImg']) {
  539.                         return '<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc"><img src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" border="0" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" hspace="2" align="middle" /></a>';
  540.                     } else {
  541.                         return '[<a href="' . $GLOBALS['cfg']['MySQLManualBase'] . '/' . $link[0] . '/' . $link[1] . '/' . $link . '.html" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  542.                    }
  543.                 } else {
  544.                     return '';
  545.                 }
  546.             }
  547.         }
  548.                  // end of the 'PMA_showDocu()' function
  549.  
  550.     /**
  551.      * Displays a hint icon, on mouse over show the hint
  552.      *
  553.      * @param   string   the error message
  554.      *
  555.      * @access  public
  556.      */
  557.      function PMA_showHint($hint_message)
  558.      {
  559.          return '<img src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" />';
  560.      }
  561.  
  562.     /**
  563.      * Displays a MySQL error message in the right frame.
  564.      *
  565.      * @param   string   the error message
  566.      * @param   string   the sql query that failed
  567.      * @param   boolean  whether to show a "modify" link or not
  568.      * @param   string   the "back" link url (full path is not required)
  569.      * @param   boolean  EXIT the page?
  570.      *
  571.      * @global  array    the configuration array
  572.      *
  573.      * @access  public
  574.      */
  575.     function PMA_mysqlDie($error_message = '', $the_query = '',
  576.                             $is_modify_link = TRUE, $back_url = '',
  577.                             $exit = TRUE)
  578.     {
  579.         global $cfg, $table, $db, $sql_query;
  580.  
  581.         require_once('./header.inc.php');
  582.  
  583.         if (!$error_message) {
  584.             $error_message = PMA_DBI_getError();
  585.         }
  586.         if (!$the_query && !empty($GLOBALS['sql_query'])) {
  587.             $the_query = $GLOBALS['sql_query'];
  588.         }
  589.  
  590.         // --- Added to solve bug #641765
  591.         // Robbat2 - 12 January 2003, 9:46PM
  592.         // Revised, Robbat2 - 13 Janurary 2003, 2:59PM
  593.         if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
  594.             $formatted_sql = htmlspecialchars($the_query);
  595.         } else {
  596.             $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
  597.         }
  598.         // ---
  599.         echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
  600.         echo '    <table border="0" cellpadding="2" cellspacing="1">'
  601.            . '        <tr>' . "\n"
  602.            . '            <th class="tblHeadError"><div class="errorhead">' . $GLOBALS['strError'] . '</div></th>' . "\n"
  603.            . '        </tr>' . "\n"
  604.            . '        <tr>' . "\n"
  605.            . '            <td>';
  606.         // if the config password is wrong, or the MySQL server does not
  607.         // respond, do not show the query that would reveal the
  608.         // username/password
  609.         if (!empty($the_query) && !strstr($the_query, 'connect')) {
  610.             // --- Added to solve bug #641765
  611.             // Robbat2 - 12 January 2003, 9:46PM
  612.             // Revised, Robbat2 - 13 Janurary 2003, 2:59PM
  613.             if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
  614.                 echo PMA_SQP_getErrorString();
  615.             }
  616.             // ---
  617.             // modified to show me the help on sql errors (Michael Keck)
  618.             echo '<div class="tblWarn"><p>' . "\n";
  619.             echo '    <b>' . $GLOBALS['strSQLQuery'] . ':</b>' . "\n";
  620.             if (strstr(strtolower($formatted_sql),'select')) { // please show me help to the error on select
  621.                 echo PMA_showMySQLDocu('Reference', 'SELECT');
  622.             }
  623.             if ($is_modify_link && isset($db)) {
  624.                 if (isset($table)) {
  625.                     $doedit_goto = '<a href="tbl_properties.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  626.                 } else {
  627.                     $doedit_goto = '<a href="db_details.php?' . PMA_generate_common_url($db) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  628.                 }
  629.                 if ($GLOBALS['cfg']['PropertiesIconic']) {
  630.                     echo $doedit_goto
  631.                        . '<img src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" border="0" hspace="2" align="middle" alt="' . $GLOBALS['strEdit'] .'" />'
  632.                        . '</a>';
  633.                 } else {
  634.                     echo '    ['
  635.                        . $doedit_goto . $GLOBALS['strEdit'] . '</a>'
  636.                        . ']' . "\n";
  637.                 }
  638.             } // end if
  639.             echo '</p>' . "\n"
  640.                     . '<p>' . "\n"
  641.                     . '    ' . $formatted_sql . "\n"
  642.                     . '</p></div>' . "\n";
  643.         } // end if
  644.  
  645.         $tmp_mysql_error = ''; // for saving the original $error_message
  646.         if (!empty($error_message)) {
  647.             $tmp_mysql_error = strtolower($error_message); // save the original $error_message
  648.             $error_message = htmlspecialchars($error_message);
  649.             $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
  650.         }
  651.         // modified to show me the help on error-returns (Michael Keck)
  652.         echo '<div class="tblWarn"><p>' . "\n"
  653.                 . '    <b>' . $GLOBALS['strMySQLSaid'] . '</b>'
  654.                 . PMA_showMySQLDocu('Error-returns', 'Error-returns')
  655.                 . "\n"
  656.                 . '</p>' . "\n";
  657.  
  658.         // The error message will be displayed within a CODE segment.
  659.         // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
  660.  
  661.         // Replace all non-single blanks with their HTML-counterpart
  662.         $error_message = str_replace('  ', '  ', $error_message);
  663.         // Replace TAB-characters with their HTML-counterpart
  664.         $error_message = str_replace("\t", '    ', $error_message);
  665.         // Replace linebreaks
  666.         $error_message = nl2br($error_message);
  667.  
  668.         echo '<code>' . "\n"
  669.             . $error_message . "\n"
  670.             . '</code><br />' . "\n";
  671.  
  672.         // feature request #1036254:
  673.         // Add a link by MySQL-Error #1062 - Duplicate entry
  674.         // 2004-10-20 by mk.keck
  675.         if (substr($error_message, 1, 4) == '1062') {
  676.         // TODO: do not assume that the error message is in English
  677.         // and do not use mysql_result()
  678.  
  679.             // explode the entry and the column
  680.             $arr_mysql_val_key = explode('entry \'',$tmp_mysql_error);
  681.             $arr_mysql_val_key = explode('\' for key',$arr_mysql_val_key[1]);
  682.             // get the duplicate value
  683.             $string_duplicate_val = trim(strtolower($arr_mysql_val_key[0]));
  684.             // get the field name ...
  685.             $string_duplicate_key = mysql_result(mysql_query("SHOW FIELDS FROM " . $table), ($arr_mysql_val_key[1]-1), 0);
  686.             $duplicate_sql_query = "SELECT * FROM " . $table . " WHERE " . $string_duplicate_key . " LIKE '" . $string_duplicate_val . "'";
  687.             echo '        <form method="post" action="read_dump.php" style="padding: 0px; margin: 0px">' ."\n"
  688.                     . '            <input type="hidden" name="sql_query" value="' . $duplicate_sql_query . '" />' . "\n"
  689.                     . '            ' . PMA_generate_common_hidden_inputs($db, $table) . "\n"
  690.                     . '            <input type="submit" name="submit" value="' . $GLOBALS['strBrowse'] . '" />' . "\n"
  691.                     . '        </form>' . "\n";
  692.         } // end of show duplicate entry
  693.  
  694.         echo '</div>';
  695.  
  696.         if (!empty($back_url) && $exit) {
  697.             $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&no_history=true' : $back_url . '?no_history=true') . '"> ';
  698.             echo '            </td> ' . "\n"
  699.                . '        </tr>' . "\n"
  700.                . '        <tr><td class="tblHeaders" align="center">';
  701.             echo '[' . $goto_back_url . $GLOBALS['strBack'] . ' </a>]';
  702.         }
  703.         echo '            </td>' . "\n"
  704.            . '        </tr>' . "\n"
  705.            . '    </table>' . "\n\n";
  706.         if ($exit) {
  707.             require_once('./footer.inc.php');
  708.         }
  709.     } // end of the 'PMA_mysqlDie()' function
  710.  
  711.  
  712.     /**
  713.      * Defines whether a string exists inside an array or not
  714.      *
  715.      * @param   string   string to search for
  716.      * @param   mixed    array to search into
  717.      *
  718.      * @return  integer  the rank of the $toFind string in the array or '-1' if
  719.      *                   it hasn't been found
  720.      *
  721.      * @access  public
  722.      */
  723.     function PMA_isInto($toFind = '', &$in)
  724.     {
  725.         $max = count($in);
  726.         for ($i = 0; $i < $max && ($toFind != $in[$i]); $i++) {
  727.             // void();
  728.         }
  729.  
  730.         return ($i < $max) ? $i : -1;
  731.     }  // end of the 'PMA_isInto()' function
  732.  
  733.  
  734.     /**
  735.      * Returns a string formatted with CONVERT ... USING
  736.      * if MySQL supports it
  737.      *
  738.      * @param   string  the string itself
  739.      * @param   string  the mode: quoted or unquoted (this one by default)
  740.      *
  741.      * @return  the formatted string
  742.      *
  743.      * @access  private
  744.      */
  745.     function PMA_convert_using($string, $mode='unquoted') {
  746.  
  747.         if ($mode == 'quoted') {
  748.             $possible_quote = "'";
  749.         } else {
  750.             $possible_quote = "";
  751.         }
  752.  
  753.         if (PMA_MYSQL_INT_VERSION >= 40100) {
  754.             list($conn_charset) = explode('_', $GLOBALS['collation_connection']);
  755.             $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $conn_charset . ")";
  756.         } else {
  757.             $converted_string = $possible_quote . $string . $possible_quote;
  758.         }
  759.         return $converted_string;
  760.     } // end function
  761.  
  762. }
  763.  
  764. /**
  765.  * Get the complete list of Databases a user can access
  766.  *
  767.  * @param   boolean   whether to include check on failed 'only_db' operations
  768.  * @param   resource  database handle (superuser)
  769.  * @param   integer   amount of databases inside the 'only_db' container
  770.  * @param   resource  possible resource from a failed previous query
  771.  * @param   resource  database handle (user)
  772.  * @param   array     configuration
  773.  * @param   array     previous list of databases
  774.  *
  775.  * @return  array     all databases a user has access to
  776.  *
  777.  * @access  private
  778.  */
  779. function PMA_safe_db_list($only_db_check, $dbh, $dblist_cnt, $rs, $userlink, $cfg, $dblist) {
  780.     if ($only_db_check == FALSE) {
  781.         // try to get the available dbs list
  782.         // use userlink by default
  783.         $dblist = PMA_DBI_get_dblist();
  784.         $dblist_cnt   = count($dblist);
  785.  
  786.         // did not work so check for available databases in the "mysql" db;
  787.         // I don't think we can fall here now...
  788.         if (!$dblist_cnt) {
  789.             $auth_query   = 'SELECT User, Select_priv '
  790.                           . 'FROM mysql.user '
  791.                           . 'WHERE User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
  792.             $rs           = PMA_DBI_try_query($auth_query, $dbh);
  793.         } // end
  794.     }
  795.  
  796.     // Access to "mysql" db allowed and dblist still empty -> gets the
  797.     // usable db list
  798.     if (!$dblist_cnt
  799.         && ($rs && @PMA_DBI_num_rows($rs))) {
  800.         $row = PMA_DBI_fetch_assoc($rs);
  801.         PMA_DBI_free_result($rs);
  802.         // Correction uva 19991215
  803.         // Previous code assumed database "mysql" admin table "db" column
  804.         // "db" contains literal name of user database, and works if so.
  805.         // Mysql usage generally (and uva usage specifically) allows this
  806.         // column to contain regular expressions (we have all databases
  807.         // owned by a given student/faculty/staff beginning with user i.d.
  808.         // and governed by default by a single set of privileges with
  809.         // regular expression as key). This breaks previous code.
  810.         // This maintenance is to fix code to work correctly for regular
  811.         // expressions.
  812.         if ($row['Select_priv'] != 'Y') {
  813.  
  814.             // 1. get allowed dbs from the "mysql.db" table
  815.             // lem9: User can be blank (anonymous user)
  816.             $local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE Select_priv = \'Y\' AND (User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\' OR User = \'\')';
  817.             $rs          = PMA_DBI_try_query($local_query, $dbh);
  818.             if ($rs && @PMA_DBI_num_rows($rs)) {
  819.                 // Will use as associative array of the following 2 code
  820.                 // lines:
  821.                 //   the 1st is the only line intact from before
  822.                 //     correction,
  823.                 //   the 2nd replaces $dblist[] = $row['Db'];
  824.                 $uva_mydbs = array();
  825.                 // Code following those 2 lines in correction continues
  826.                 // populating $dblist[], as previous code did. But it is
  827.                 // now populated with actual database names instead of
  828.                 // with regular expressions.
  829.                 while ($row = PMA_DBI_fetch_assoc($rs)) {
  830.                     // loic1: all databases cases - part 1
  831.                     if (empty($row['Db']) || $row['Db'] == '%') {
  832.                         $uva_mydbs['%'] = 1;
  833.                         break;
  834.                     }
  835.                     // loic1: avoid multiple entries for dbs
  836.                     if (!isset($uva_mydbs[$row['Db']])) {
  837.                         $uva_mydbs[$row['Db']] = 1;
  838.                     }
  839.                 } // end while
  840.                 PMA_DBI_free_result($rs);
  841.                 $uva_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['dbh']);
  842.                 // loic1: all databases cases - part 2
  843.                 if (isset($uva_mydbs['%'])) {
  844.                     while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
  845.                         $dblist[] = $uva_row[0];
  846.                     } // end while
  847.                 } // end if
  848.                 else {
  849.                     while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
  850.                         $uva_db = $uva_row[0];
  851.                         if (isset($uva_mydbs[$uva_db]) && $uva_mydbs[$uva_db] == 1) {
  852.                             $dblist[]           = $uva_db;
  853.                             $uva_mydbs[$uva_db] = 0;
  854.                         } else if (!isset($dblist[$uva_db])) {
  855.                             foreach ($uva_mydbs AS $uva_matchpattern => $uva_value) {
  856.                                 // loic1: fixed bad regexp
  857.                                 // TODO: db names may contain characters
  858.                                 //       that are regexp instructions
  859.                                 $re        = '(^|(\\\\\\\\)+|[^\])';
  860.                                 $uva_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $uva_matchpattern));
  861.                                 // Fixed db name matching
  862.                                 // 2000-08-28 -- Benjamin Gandon
  863.                                 if (ereg('^' . $uva_regex . '$', $uva_db)) {
  864.                                     $dblist[] = $uva_db;
  865.                                     break;
  866.                                 }
  867.                             } // end while
  868.                         } // end if ... else if....
  869.                     } // end while
  870.                 } // end else
  871.                 PMA_DBI_free_result($uva_alldbs);
  872.                 unset($uva_mydbs);
  873.             } // end if
  874.  
  875.             // 2. get allowed dbs from the "mysql.tables_priv" table
  876.             $local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
  877.             $rs          = PMA_DBI_try_query($local_query, $dbh);
  878.             if ($rs && @PMA_DBI_num_rows($rs)) {
  879.                 while ($row = PMA_DBI_fetch_assoc($rs)) {
  880.                     if (PMA_isInto($row['Db'], $dblist) == -1) {
  881.                         $dblist[] = $row['Db'];
  882.                     }
  883.                 } // end while
  884.                 PMA_DBI_free_result($rs);
  885.             } // end if
  886.         } // end if
  887.     } // end building available dbs from the "mysql" db
  888.  
  889.     return $dblist;
  890. }
  891.  
  892. /**
  893.  * Determines the font sizes to use depending on the os and browser of the
  894.  * user.
  895.  *
  896.  * This function is based on an article from phpBuilder (see
  897.  * http://www.phpbuilder.net/columns/tim20000821.php).
  898.  *
  899.  * @return  boolean    always true
  900.  *
  901.  * @global  string     the standard font size
  902.  * @global  string     the font size for titles
  903.  * @global  string     the small font size
  904.  * @global  string     the smallest font size
  905.  *
  906.  * @access  public
  907.  *
  908.  * @version 1.1
  909.  */
  910. function PMA_setFontSizes()
  911. {
  912.     global $font_size, $font_biggest, $font_bigger, $font_smaller, $font_smallest;
  913.  
  914.     // IE (<7)/Opera (<7) for win case: needs smaller fonts than anyone else
  915.     if (PMA_USR_OS == 'Win'
  916.         && ((PMA_USR_BROWSER_AGENT == 'IE' && PMA_USR_BROWSER_VER < 7)
  917.         || (PMA_USR_BROWSER_AGENT == 'OPERA' && PMA_USR_BROWSER_VER < 7))) {
  918.         $font_size     = 'x-small';
  919.         $font_biggest  = 'large';
  920.         $font_bigger   = 'medium';
  921.         $font_smaller  = '90%';
  922.         $font_smallest = '7pt';
  923.     }
  924.     // IE6 and other browsers for win case
  925.     else if (PMA_USR_OS == 'Win') {
  926.         $font_size     = 'small';
  927.         $font_biggest  = 'large';
  928.         $font_bigger   = 'medium';
  929.         $font_smaller  = (PMA_USR_BROWSER_AGENT == 'IE')
  930.                         ? '90%'
  931.                         : 'x-small';
  932.         $font_smallest = 'x-small';
  933.     }
  934.     // Some mac browsers need also smaller default fonts size (OmniWeb &
  935.     // Opera)...
  936.     // and a beta version of Safari did also, but not the final 1.0 version
  937.     // so I remove   || PMA_USR_BROWSER_AGENT == 'SAFARI'
  938.     // but we got a report that Safari 1.0 build 85.5 needs it!
  939.  
  940.     else if (PMA_USR_OS == 'Mac'
  941.                 && (PMA_USR_BROWSER_AGENT == 'OMNIWEB' || PMA_USR_BROWSER_AGENT == 'OPERA' || PMA_USR_BROWSER_AGENT == 'SAFARI')) {
  942.         $font_size     = 'x-small';
  943.         $font_biggest  = 'large';
  944.         $font_bigger   = 'medium';
  945.         $font_smaller  = '90%';
  946.         $font_smallest = '7pt';
  947.     }
  948.     // ... but most of them (except IE 5+ & NS 6+) need bigger fonts
  949.     else if ((PMA_USR_OS == 'Mac'
  950.                 && ((PMA_USR_BROWSER_AGENT != 'IE' && PMA_USR_BROWSER_AGENT != 'MOZILLA')
  951.                     || PMA_USR_BROWSER_VER < 5))
  952.             || PMA_USR_BROWSER_AGENT == 'KONQUEROR') {
  953.         $font_size     = 'medium';
  954.         $font_biggest  = 'x-large';
  955.         $font_bigger   = 'large';
  956.         $font_smaller  = 'small';
  957.         $font_smallest = 'x-small';
  958.     }
  959.     // OS/2 browser
  960.     else if (PMA_USR_OS == 'OS/2'
  961.                 && PMA_USR_BROWSER_AGENT == 'OPERA') {
  962.         $font_size     = 'small';
  963.         $font_biggest  = 'medium';
  964.         $font_bigger   = 'medium';
  965.         $font_smaller  = 'x-small';
  966.         $font_smallest = 'x-small';
  967.     }
  968.     else {
  969.         $font_size     = 'small';
  970.         $font_biggest  = 'large';
  971.         $font_bigger   = 'medium';
  972.         $font_smaller  = 'x-small';
  973.         $font_smallest = 'x-small';
  974.     }
  975.  
  976.     return TRUE;
  977. } // end of the 'PMA_setFontSizes()' function
  978.  
  979.  
  980. if ($is_minimum_common == FALSE) {
  981.     /**
  982.      * $cfg['PmaAbsoluteUri'] is a required directive else cookies won't be
  983.      * set properly and, depending on browsers, inserting or updating a
  984.      * record might fail
  985.      */
  986.     $display_pmaAbsoluteUri_warning = 0;
  987.  
  988.     // Setup a default value to let the people and lazy syadmins work anyway,
  989.     // but display a big warning on the main.php page.
  990.     if (empty($cfg['PmaAbsoluteUri'])) {
  991.  
  992.         $url = array();
  993.  
  994.         // At first we try to parse REQUEST_URI, it might contain full URI
  995.         if (!empty($_SERVER['REQUEST_URI'])) {
  996.             $url = parse_url($_SERVER['REQUEST_URI']);
  997.         }
  998.  
  999.         // If we don't have scheme, we didn't have full URL so we need to dig deeper
  1000.         if (empty($url['scheme'])) {
  1001.             // Scheme
  1002.             if (!empty($_SERVER['HTTP_SCHEME'])) {
  1003.                 $url['scheme'] = $_SERVER['HTTP_SCHEME'];
  1004.             } else {
  1005.                 $url['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http';
  1006.             }
  1007.  
  1008.             // Host and port
  1009.             if (!empty($_SERVER['HTTP_HOST'])) {
  1010.                 if (strpos($_SERVER['HTTP_HOST'], ':') > 0) {
  1011.                     list($url['host'], $url['port']) = explode(':', $_SERVER['HTTP_HOST']);
  1012.                 } else {
  1013.                     $url['host'] = $_SERVER['HTTP_HOST'];
  1014.                 }
  1015.             } else if (!empty($_SERVER['SERVER_NAME'])) {
  1016.                 $url['host'] = $_SERVER['SERVER_NAME'];
  1017.             } else {
  1018.                 header('Content-Type: text/html; charset=' . $charset);
  1019.                 // Displays the error message
  1020.                 ?>
  1021. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  1022. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  1023. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $available_languages[$lang][2]; ?>" lang="<?php echo $available_languages[$lang][2]; ?>" dir="<?php echo $text_dir; ?>">
  1024.  
  1025. <head>
  1026. <title>phpMyAdmin</title>
  1027. <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $charset; ?>" />
  1028.  
  1029. <style type="text/css">
  1030. <!--
  1031. body  {font-family: sans-serif; font-size: small; color: #000000; background-color: #F5F5F5}
  1032. h1    {font-family: sans-serif; font-size: large; font-weight: bold}
  1033. //-->
  1034. </style>
  1035. </head>
  1036.  
  1037.  
  1038. <body bgcolor="#ffffff">
  1039. <h1>phpMyAdmin - <?php echo $strError; ?></h1>
  1040. <p>
  1041. <?php echo $strPmaUriError; ?><br /><br />
  1042. </p>
  1043. </body>
  1044.  
  1045. </html>
  1046.                 <?php
  1047.                 exit();
  1048.             }
  1049.  
  1050.             // If we didn't set port yet...
  1051.             if (empty($url['port']) && !empty($_SERVER['SERVER_PORT'])) {
  1052.                 $url['port'] = $_SERVER['SERVER_PORT'];
  1053.             }
  1054.  
  1055.             // And finally the path could be already set from REQUEST_URI
  1056.             if (empty($url['path'])) {
  1057.                 if (!empty($_SERVER['PATH_INFO'])) {
  1058.                     $path = parse_url($_SERVER['PATH_INFO']);
  1059.                 } else {
  1060.                     // PHP_SELF in CGI often points to cgi executable, so use it as last choice
  1061.                     $path = parse_url($_SERVER['PHP_SELF']);
  1062.                 }
  1063.                 $url['path'] = $path['path'];
  1064.                 unset($path);
  1065.             }
  1066.         }
  1067.  
  1068.         // Make url from parts we have
  1069.         $cfg['PmaAbsoluteUri'] = $url['scheme'] . '://';
  1070.         // Was there user information?
  1071.         if (!empty($url['user'])) {
  1072.             $cfg['PmaAbsoluteUri'] .= $url['user'];
  1073.             if (!empty($url['pass'])) {
  1074.                 $cfg['PmaAbsoluteUri'] .= ':' . $url['pass'];
  1075.             }
  1076.             $cfg['PmaAbsoluteUri'] .= '@';
  1077.         }
  1078.         // Add hostname
  1079.         $cfg['PmaAbsoluteUri'] .= $url['host'];
  1080.         // Add port, if it not the default one
  1081.         if (!empty($url['port']) && (($url['scheme'] == 'http' && $url['port'] != 80) || ($url['scheme'] == 'https' && $url['port'] != 443))) {
  1082.             $cfg['PmaAbsoluteUri'] .= ':' . $url['port'];
  1083.         }
  1084.         // And finally path, without script name
  1085.         $cfg['PmaAbsoluteUri'] .= substr($url['path'], 0, strrpos($url['path'], '/') + 1);
  1086.  
  1087.         unset($url);
  1088.  
  1089.         // We display the warning by default, but not if it is disabled thru
  1090.         // via the $cfg['PmaAbsoluteUri_DisableWarning'] variable.
  1091.         // This is intended for sysadmins that actually want the default
  1092.         // behaviour of auto-detection due to their setup.
  1093.         // See the mailing list message:
  1094.         // http://sourceforge.net/mailarchive/forum.php?thread_id=859093&forum_id=2141
  1095.         if ($cfg['PmaAbsoluteUri_DisableWarning'] == FALSE) {
  1096.             $display_pmaAbsoluteUri_warning = 1;
  1097.         }
  1098.     } else {
  1099.         // The URI is specified, however users do often specify this
  1100.         // wrongly, so we try to fix this.
  1101.  
  1102.         // Adds a trailing slash et the end of the phpMyAdmin uri if it
  1103.         // does not exist.
  1104.         if (substr($cfg['PmaAbsoluteUri'], -1) != '/') {
  1105.             $cfg['PmaAbsoluteUri'] .= '/';
  1106.         }
  1107.  
  1108.         // If URI doesn't start with http:// or https://, we will add
  1109.         // this.
  1110.         if (substr($cfg['PmaAbsoluteUri'], 0, 7) != 'http://' && substr($cfg['PmaAbsoluteUri'], 0, 8) != 'https://') {
  1111.             $cfg['PmaAbsoluteUri']          = ((!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http') . ':'
  1112.                                             . (substr($cfg['PmaAbsoluteUri'], 0, 2) == '//' ? '' : '//')
  1113.                                             . $cfg['PmaAbsoluteUri'];
  1114.         }
  1115.     }
  1116.  
  1117.     $dblist       = array();
  1118.  
  1119.     /**
  1120.      * Gets the valid servers list and parameters
  1121.      */
  1122.     foreach ($cfg['Servers'] AS $key => $val) {
  1123.         // Don't use servers with no hostname
  1124.         if ( ($val['connect_type'] == 'tcp') && empty($val['host'])) {
  1125.             unset($cfg['Servers'][$key]);
  1126.         }
  1127.  
  1128.         // Final solution to bug #582890
  1129.         // If we are using a socket connection
  1130.         // and there is nothing in the verbose server name
  1131.         // or the host field, then generate a name for the server
  1132.         // in the form of "Server 2", localized of course!
  1133.         if ( ($val['connect_type'] == 'socket') && empty($val['host']) && empty($val['verbose']) ) {
  1134.             $cfg['Servers'][$key]['verbose'] = $GLOBALS['strServer'] . $key;
  1135.             $val['verbose']                  = $GLOBALS['strServer'] . $key;
  1136.         }
  1137.     }
  1138.  
  1139.     if (empty($server) || !isset($cfg['Servers'][$server]) || !is_array($cfg['Servers'][$server])) {
  1140.         $server = $cfg['ServerDefault'];
  1141.     }
  1142.  
  1143.  
  1144.     /**
  1145.      * If no server is selected, make sure that $cfg['Server'] is empty (so
  1146.      * that nothing will work), and skip server authentication.
  1147.      * We do NOT exit here, but continue on without logging into any server.
  1148.      * This way, the welcome page will still come up (with no server info) and
  1149.      * present a choice of servers in the case that there are multiple servers
  1150.      * and '$cfg['ServerDefault'] = 0' is set.
  1151.      */
  1152.     if ($server == 0) {
  1153.         $cfg['Server'] = array();
  1154.     }
  1155.  
  1156.     /**
  1157.      * Otherwise, set up $cfg['Server'] and do the usual login stuff.
  1158.      */
  1159.     else if (isset($cfg['Servers'][$server])) {
  1160.         $cfg['Server'] = $cfg['Servers'][$server];
  1161.  
  1162.         /**
  1163.          * Loads the proper database interface for this server
  1164.          */
  1165.         require_once('./libraries/database_interface.lib.php');
  1166.  
  1167.         // Gets the authentication library that fits the $cfg['Server'] settings
  1168.         // and run authentication
  1169.  
  1170.         // (for a quick check of path disclosure in auth/cookies:)
  1171.         $coming_from_common = TRUE;
  1172.  
  1173.         require_once('./libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php');
  1174.         if (!PMA_auth_check()) {
  1175.             PMA_auth();
  1176.         } else {
  1177.             PMA_auth_set_user();
  1178.         }
  1179.  
  1180.         // Check IP-based Allow/Deny rules as soon as possible to reject the
  1181.         // user
  1182.         // Based on mod_access in Apache:
  1183.         // http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/aaa/mod_access.c?rev=1.37&content-type=text/vnd.viewcvs-markup
  1184.         // Look at: "static int check_dir_access(request_rec *r)"
  1185.         // Robbat2 - May 10, 2002
  1186.         if (isset($cfg['Server']['AllowDeny']) && isset($cfg['Server']['AllowDeny']['order'])) {
  1187.             require_once('./libraries/ip_allow_deny.lib.php');
  1188.  
  1189.             $allowDeny_forbidden         = FALSE; // default
  1190.             if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') {
  1191.                 $allowDeny_forbidden     = TRUE;
  1192.                 if (PMA_allowDeny('allow')) {
  1193.                     $allowDeny_forbidden = FALSE;
  1194.                 }
  1195.                 if (PMA_allowDeny('deny')) {
  1196.                     $allowDeny_forbidden = TRUE;
  1197.                 }
  1198.             } else if ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') {
  1199.                 if (PMA_allowDeny('deny')) {
  1200.                     $allowDeny_forbidden = TRUE;
  1201.                 }
  1202.                 if (PMA_allowDeny('allow')) {
  1203.                     $allowDeny_forbidden = FALSE;
  1204.                 }
  1205.             } else if ($cfg['Server']['AllowDeny']['order'] == 'explicit') {
  1206.                 if (PMA_allowDeny('allow')
  1207.                     && !PMA_allowDeny('deny')) {
  1208.                     $allowDeny_forbidden = FALSE;
  1209.                 } else {
  1210.                     $allowDeny_forbidden = TRUE;
  1211.                 }
  1212.             } // end if... else if... else if
  1213.  
  1214.             // Ejects the user if banished
  1215.             if ($allowDeny_forbidden) {
  1216.                PMA_auth_fails();
  1217.             }
  1218.             unset($allowDeny_forbidden); //Clean up after you!
  1219.         } // end if
  1220.  
  1221.         // is root allowed?
  1222.         if (!$cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') {
  1223.             $allowDeny_forbidden = TRUE;
  1224.             PMA_auth_fails();
  1225.             unset($allowDeny_forbidden); //Clean up after you!
  1226.         }
  1227.  
  1228.         // The user can work with only some databases
  1229.         if (isset($cfg['Server']['only_db']) && $cfg['Server']['only_db'] != '') {
  1230.             if (is_array($cfg['Server']['only_db'])) {
  1231.                 $dblist   = $cfg['Server']['only_db'];
  1232.             } else {
  1233.                 $dblist[] = $cfg['Server']['only_db'];
  1234.             }
  1235.         } // end if
  1236.  
  1237.         $bkp_track_err = @ini_set('track_errors', 1);
  1238.  
  1239.         // Try to connect MySQL with the control user profile (will be used to
  1240.         // get the privileges list for the current user but the true user link
  1241.         // must be open after this one so it would be default one for all the
  1242.         // scripts)
  1243.         if ($cfg['Server']['controluser'] != '') {
  1244.             $dbh = PMA_DBI_connect($cfg['Server']['controluser'], $cfg['Server']['controlpass']);
  1245.         } // end if ... else
  1246.  
  1247.         // Pass #1 of DB-Config to read in master level DB-Config will go here
  1248.         // Robbat2 - May 11, 2002
  1249.  
  1250.         // Connects to the server (validates user's login)
  1251.         $userlink = PMA_DBI_connect($cfg['Server']['user'], $cfg['Server']['password']);
  1252.  
  1253.         if (empty($dbh)) {
  1254.             $dbh = $userlink;
  1255.         }
  1256.  
  1257.         // Pass #2 of DB-Config to read in user level DB-Config will go here
  1258.         // Robbat2 - May 11, 2002
  1259.  
  1260.         @ini_set('track_errors', $bkp_track_err);
  1261.         unset($bkp_track_err);
  1262.  
  1263.         /**
  1264.          * SQL Parser code
  1265.          */
  1266.         require_once('./libraries/sqlparser.lib.php');
  1267.  
  1268.         /**
  1269.          * SQL Validator interface code
  1270.          */
  1271.         require_once('./libraries/sqlvalidator.lib.php');
  1272.  
  1273.         // if 'only_db' is set for the current user, there is no need to check for
  1274.         // available databases in the "mysql" db
  1275.         $dblist_cnt = count($dblist);
  1276.         if ($dblist_cnt) {
  1277.             $true_dblist  = array();
  1278.             $is_show_dbs  = TRUE;
  1279.  
  1280.             $dblist_asterisk_bool = FALSE;
  1281.             for ($i = 0; $i < $dblist_cnt; $i++) {
  1282.  
  1283.                 // The current position
  1284.                 if ($dblist[$i] == '*' && $dblist_asterisk_bool == FALSE) {
  1285.                     $dblist_asterisk_bool = TRUE;
  1286.                     $dblist_full = PMA_safe_db_list(FALSE, $dbh, FALSE, $rs, $userlink, $cfg, $dblist);
  1287.                     foreach ($dblist_full AS $dbl_key => $dbl_val) {
  1288.                         if (!in_array($dbl_val, $dblist)) {
  1289.                             $true_dblist[] = $dbl_val;
  1290.                         }
  1291.                     }
  1292.  
  1293.                     continue;
  1294.                 } elseif ($dblist[$i] == '*') {
  1295.                     // We don't want more than one asterisk inside our 'only_db'.
  1296.                     continue;
  1297.                 }
  1298.                 if ($is_show_dbs && ereg('(^|[^\])(_|%)', $dblist[$i])) {
  1299.                     $local_query = 'SHOW DATABASES LIKE \'' . $dblist[$i] . '\'';
  1300.                     $rs          = PMA_DBI_query($local_query, $dbh);
  1301.                     // "SHOW DATABASES" statement is disabled
  1302.                     if ($i == 0
  1303.                         && (substr(PMA_DBI_getError($dbh), 1, 4) == 1045)) {
  1304.                         $true_dblist[] = str_replace('\\_', '_', str_replace('\\%', '%', $dblist[$i]));
  1305.                         $is_show_dbs   = FALSE;
  1306.                     }
  1307.                     // Debug
  1308.                     // else if (PMA_DBI_getError($dbh)) {
  1309.                     //    PMA_mysqlDie(PMA_DBI_getError($dbh), $local_query, FALSE);
  1310.                     // }
  1311.                     while ($row = @PMA_DBI_fetch_row($rs)) {
  1312.                         $true_dblist[] = $row[0];
  1313.                     } // end while
  1314.                     if ($rs) {
  1315.                         PMA_DBI_free_result($rs);
  1316.                     }
  1317.                 } else {
  1318.                     $true_dblist[]     = str_replace('\\_', '_', str_replace('\\%', '%', $dblist[$i]));
  1319.                 } // end if... else...
  1320.             } // end for
  1321.             $dblist       = $true_dblist;
  1322.             unset($true_dblist);
  1323.             $only_db_check = TRUE;
  1324.         } // end if
  1325.  
  1326.         // 'only_db' is empty for the current user...
  1327.         else {
  1328.             $only_db_check = FALSE;
  1329.         } // end if (!$dblist_cnt)
  1330.  
  1331.         if (isset($dblist_full) && !count($dblist_full)) {
  1332.             $dblist = PMA_safe_db_list($only_db_check, $dbh, $dblist_cnt, $rs, $userlink, $cfg, $dblist);
  1333.         }
  1334.  
  1335.     } // end server connecting
  1336.     /**
  1337.      * Missing server hostname
  1338.      */
  1339.     else {
  1340.         echo $strHostEmpty;
  1341.     }
  1342.  
  1343.     /**
  1344.      * Send HTTP header, taking IIS limits into account
  1345.      *                   ( 600 seems ok)
  1346.      *
  1347.      * @param   string   the header to send
  1348.      *
  1349.      * @return  boolean  always true
  1350.      */
  1351.      function PMA_sendHeaderLocation($uri)
  1352.      {
  1353.          if (PMA_IS_IIS && strlen($uri) > 600) {
  1354.  
  1355.              echo '<html><head><title>- - -</title>' . "\n";
  1356.              echo '<meta http-equiv="expires" content="0">' . "\n";
  1357.              echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
  1358.              echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
  1359.              echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
  1360.              echo '<script language="JavaScript">' . "\n";
  1361.              echo 'setTimeout ("window.location = unescape(\'"' . $uri . '"\')",2000); </script>' . "\n";
  1362.              echo '</head>' . "\n";
  1363.              echo '<body> <script language="JavaScript">' . "\n";
  1364.              echo 'document.write (\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
  1365.              echo '</script></body></html>' . "\n";
  1366.  
  1367.          } else {
  1368.              header('Location: ' . $uri);
  1369.          }
  1370.      }
  1371.  
  1372.  
  1373.     /**
  1374.      * Get the list and number of available databases.
  1375.      *
  1376.      * @param   string   the url to go back to in case of error
  1377.      *
  1378.      * @return  boolean  always true
  1379.      *
  1380.      * @global  array    the list of available databases
  1381.      * @global  integer  the number of available databases
  1382.      * @global  array    current configuration
  1383.      */
  1384.     function PMA_availableDatabases($error_url = '')
  1385.     {
  1386.         global $dblist;
  1387.         global $num_dbs;
  1388.         global $cfg;
  1389.  
  1390.         $num_dbs = count($dblist);
  1391.  
  1392.         // 1. A list of allowed databases has already been defined by the
  1393.         //    authentification process -> gets the available databases list
  1394.         if ($num_dbs) {
  1395.             $true_dblist = array();
  1396.             for ($i = 0; $i < $num_dbs; $i++) {
  1397.                 $dblink  = @PMA_DBI_select_db($dblist[$i]);
  1398.                 if ($dblink) {
  1399.                     $true_dblist[] = $dblist[$i];
  1400.                 } // end if
  1401.             } // end for
  1402.             $dblist      = array();
  1403.             $dblist      = $true_dblist;
  1404.             unset($true_dblist);
  1405.             $num_dbs     = count($dblist);
  1406.         } // end if
  1407.         // 2. Allowed database list is empty -> gets the list of all databases
  1408.         //    on the server
  1409.         else if (!isset($cfg['Server']['only_db']) || $cfg['Server']['only_db'] == '') {
  1410.             $dblist = PMA_DBI_get_dblist(); // needed? or PMA_mysqlDie('', 'SHOW DATABASES;', FALSE, $error_url);
  1411.             $num_dbs = count($dblist);
  1412.         } // end else
  1413.  
  1414.         return TRUE;
  1415.     } // end of the 'PMA_availableDatabases()' function
  1416.  
  1417.  
  1418.  
  1419.     /* ----------------------- Set of misc functions ----------------------- */
  1420.  
  1421.  
  1422.     /**
  1423.      * Adds backquotes on both sides of a database, table or field name.
  1424.      * Since MySQL 3.23.6 this allows to use non-alphanumeric characters in
  1425.      * these names.
  1426.      *
  1427.      * @param   mixed    the database, table or field name to "backquote" or
  1428.      *                   array of it
  1429.      * @param   boolean  a flag to bypass this function (used by dump
  1430.      *                   functions)
  1431.      *
  1432.      * @return  mixed    the "backquoted" database, table or field name if the
  1433.      *                   current MySQL release is >= 3.23.6, the original one
  1434.      *                   else
  1435.      *
  1436.      * @access  public
  1437.      */
  1438.     function PMA_backquote($a_name, $do_it = TRUE)
  1439.     {
  1440.         // '0' is also empty for php :-(
  1441.         if ($do_it
  1442.             && (!empty($a_name) || $a_name == '0') && $a_name != '*') {
  1443.  
  1444.             if (is_array($a_name)) {
  1445.                  $result = array();
  1446.                  foreach ($a_name AS $key => $val) {
  1447.                      $result[$key] = '`' . $val . '`';
  1448.                  }
  1449.                  return $result;
  1450.             } else {
  1451.                 return '`' . $a_name . '`';
  1452.             }
  1453.         } else {
  1454.             return $a_name;
  1455.         }
  1456.     } // end of the 'PMA_backquote()' function
  1457.  
  1458.  
  1459.     /**
  1460.      * Format a string so it can be passed to a javascript function.
  1461.      * This function is used to displays a javascript confirmation box for
  1462.      * "DROP/DELETE/ALTER" queries.
  1463.      *
  1464.      * @param   string   the string to format
  1465.      * @param   boolean  whether to add backquotes to the string or not
  1466.      *
  1467.      * @return  string   the formated string
  1468.      *
  1469.      * @access  public
  1470.      */
  1471.     function PMA_jsFormat($a_string = '', $add_backquotes = TRUE)
  1472.     {
  1473.         if (is_string($a_string)) {
  1474.             $a_string = htmlspecialchars($a_string);
  1475.             $a_string = str_replace('\\', '\\\\', $a_string);
  1476.             $a_string = str_replace('\'', '\\\'', $a_string);
  1477.             $a_string = str_replace('#', '\\#', $a_string);
  1478.             $a_string = str_replace("\012", '\\\\n', $a_string);
  1479.             $a_string = str_replace("\015", '\\\\r', $a_string);
  1480.         }
  1481.  
  1482.         return (($add_backquotes) ? PMA_backquote($a_string) : $a_string);
  1483.     } // end of the 'PMA_jsFormat()' function
  1484.  
  1485.  
  1486.     /**
  1487.      * Defines the <CR><LF> value depending on the user OS.
  1488.      *
  1489.      * @return  string   the <CR><LF> value to use
  1490.      *
  1491.      * @access  public
  1492.      */
  1493.     function PMA_whichCrlf()
  1494.     {
  1495.         $the_crlf = "\n";
  1496.  
  1497.         // The 'PMA_USR_OS' constant is defined in "./libraries/defines.lib.php"
  1498.         // Win case
  1499.         if (PMA_USR_OS == 'Win') {
  1500.             $the_crlf = "\r\n";
  1501.         }
  1502.         // Mac case
  1503.         else if (PMA_USR_OS == 'Mac') {
  1504.             $the_crlf = "\r";
  1505.         }
  1506.         // Others
  1507.         else {
  1508.             $the_crlf = "\n";
  1509.         }
  1510.  
  1511.         return $the_crlf;
  1512.     } // end of the 'PMA_whichCrlf()' function
  1513.  
  1514.  
  1515.     /**
  1516.      * Counts and displays the number of records in a table
  1517.      *
  1518.      * Last revision 13 July 2001: Patch for limiting dump size from
  1519.      * vinay@sanisoft.com & girish@sanisoft.com
  1520.      *
  1521.      * @param   string   the current database name
  1522.      * @param   string   the current table name
  1523.      * @param   boolean  whether to retain or to displays the result
  1524.      *
  1525.      * @return  mixed    the number of records if retain is required, true else
  1526.      *
  1527.      * @access  public
  1528.      */
  1529.     function PMA_countRecords($db, $table, $ret = FALSE)
  1530.     {
  1531.         global $err_url, $cfg;
  1532.         $result       = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, TRUE) . '\';');
  1533.         $showtable    = PMA_DBI_fetch_assoc($result);
  1534.         $num     = (isset($showtable['Rows']) ? $showtable['Rows'] : 0);
  1535.         if ($num < $cfg['MaxExactCount']) {
  1536.             unset($num);
  1537.         }
  1538.         PMA_DBI_free_result($result);
  1539.  
  1540.         if (!isset($num)) {
  1541.             $result    = PMA_DBI_query('SELECT COUNT(*) AS num FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table));
  1542.             list($num) = ($result) ? PMA_DBI_fetch_row($result) : array(0);
  1543.             PMA_DBI_free_result($result);
  1544.         }
  1545.         if ($ret) {
  1546.             return $num;
  1547.         } else {
  1548.             echo number_format($num, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
  1549.             return TRUE;
  1550.         }
  1551.     } // end of the 'PMA_countRecords()' function
  1552.  
  1553.     /**
  1554.      * Reloads navigation if needed.
  1555.      *
  1556.      * @global  mixed   configuration
  1557.      * @global  bool    whether to reload
  1558.      *
  1559.      * @access  public
  1560.      */
  1561.     function PMA_reloadNavigation() {
  1562.         global $cfg;
  1563.  
  1564.         // Reloads the navigation frame via JavaScript if required
  1565.         if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
  1566.             echo "\n";
  1567.             $reload_url = './left.php?' . PMA_generate_common_url((isset($GLOBALS['db']) ? $GLOBALS['db'] : ''), '', '&');
  1568.             ?>
  1569. <script type="text/javascript" language="javascript1.2">
  1570. <!--
  1571. if (typeof(window.parent) != 'undefined'
  1572.     && typeof(window.parent.frames['nav']) != 'undefined') {
  1573.     window.parent.frames['nav'].goTo('<?php echo $reload_url; ?>&hash=' + <?php echo (($cfg['QueryFrame'] && $cfg['QueryFrameJS']) ? 'window.parent.frames[\'queryframe\'].document.hashform.hash.value' : "'" . md5($cfg['PmaAbsoluteUri']) . "'"); ?>);
  1574. }
  1575. //-->
  1576. </script>
  1577.             <?php
  1578.             unset($GLOBALS['reload']);
  1579.         }
  1580.     }
  1581.  
  1582.     /**
  1583.      * Sanitizes $message, taking into account our special codes
  1584.      * for formatting
  1585.      *
  1586.      * @param   string   the message
  1587.      *
  1588.      * @return  string   the sanitized message
  1589.      *
  1590.      * @access  public
  1591.      */
  1592.     function PMA_sanitize($message)
  1593.     {
  1594.         $replace_pairs = array(
  1595.             '<'     => '<',
  1596.             '>'     => '>',
  1597.             '[i]'   => '<i>',
  1598.             '[/i]'  => '</i>',
  1599.             '[b]'   => '<b>',
  1600.             '[br]'  => '<br />',
  1601.             '[/b]'  => '</b>',
  1602.         );
  1603.         return strtr($message, $replace_pairs);
  1604.     }
  1605.  
  1606.     /**
  1607.      * Displays a message at the top of the "main" (right) frame
  1608.      *
  1609.      * @param   string  the message to display
  1610.      *
  1611.      * @global  array   the configuration array
  1612.      *
  1613.      * @access  public
  1614.      */
  1615.     function PMA_showMessage($message)
  1616.     {
  1617.         global $cfg;
  1618.  
  1619.         // Sanitizes $message
  1620.         $message = PMA_sanitize($message);
  1621.  
  1622.         // Corrects the tooltip text via JS if required
  1623.         if (!empty($GLOBALS['table']) && $cfg['ShowTooltip']) {
  1624.             $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], TRUE) . '\'');
  1625.             if ($result) {
  1626.                 $tbl_status = PMA_DBI_fetch_assoc($result);
  1627.                 $tooltip    = (empty($tbl_status['Comment']))
  1628.                             ? ''
  1629.                             : $tbl_status['Comment'] . ' ';
  1630.                 $tooltip .= '(' . $tbl_status['Rows'] . ' ' . $GLOBALS['strRows'] . ')';
  1631.                 PMA_DBI_free_result($result);
  1632.                 $md5_tbl = md5($GLOBALS['table']);
  1633.                 echo "\n";
  1634.                 ?>
  1635. <script type="text/javascript" language="javascript1.2">
  1636. <!--
  1637. if (typeof(document.getElementById) != 'undefined'
  1638.     && typeof(window.parent.frames['nav']) != 'undefined'
  1639.     && typeof(window.parent.frames['nav'].document) != 'undefined' && typeof(window.parent.frames['nav'].document) != 'unknown'
  1640.     && (window.parent.frames['nav'].document.getElementById('<?php echo 'tbl_' . $md5_tbl; ?>'))
  1641.     && typeof(window.parent.frames['nav'].document.getElementById('<?php echo 'tbl_' . $md5_tbl; ?>')) != 'undefined'
  1642.     && typeof(window.parent.frames['nav'].document.getElementById('<?php echo 'tbl_' . $md5_tbl; ?>').title) == 'string') {
  1643.     window.parent.frames['nav'].document.getElementById('<?php echo 'tbl_' . $md5_tbl; ?>').title = '<?php echo PMA_jsFormat($tooltip, FALSE); ?>';
  1644. }
  1645. //-->
  1646. </script>
  1647.                 <?php
  1648.             } // end if
  1649.         } // end if... else if
  1650.  
  1651.         // Checks if the table needs to be repaired after a TRUNCATE query.
  1652.         if (isset($GLOBALS['table']) && isset($GLOBALS['sql_query'])
  1653.             && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
  1654.             if (!isset($tbl_status)) {
  1655.                 $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], TRUE) . '\'');
  1656.                 if ($result) {
  1657.                     $tbl_status = PMA_DBI_fetch_assoc($result);
  1658.                     PMA_DBI_free_result($result);
  1659.                 }
  1660.             }
  1661.             if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {
  1662.                 PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
  1663.             }
  1664.         }
  1665.         unset($tbl_status);
  1666.  
  1667.         echo "\n";
  1668.         ?>
  1669. <br />
  1670. <div align="<?php echo $GLOBALS['cell_align_left']; ?>">
  1671.     <table border="<?php echo $cfg['Border']; ?>" cellpadding="5" cellspacing="1">
  1672.     <tr>
  1673.         <th<?php echo ($GLOBALS['theme'] != 'original') ? ' class="tblHeaders"' : ' bgcolor="' . $cfg['ThBgcolor'] . '"'; ?>>
  1674.             <b><?php echo $message; ?></b>
  1675.         </th>
  1676.     </tr>
  1677.         <?php
  1678.         if ($cfg['ShowSQL'] == TRUE && (!empty($GLOBALS['sql_query']) || !empty($GLOBALS['display_query']))) {
  1679.             $local_query = !empty($GLOBALS['display_query']) ? $GLOBALS['display_query'] : (($cfg['SQP']['fmtType'] == 'none' && isset($GLOBALS['unparsed_sql']) && $GLOBALS['unparsed_sql'] != '') ? $GLOBALS['unparsed_sql'] : $GLOBALS['sql_query']);
  1680.             // Basic url query part
  1681.             $url_qpart = '?' . PMA_generate_common_url(isset($GLOBALS['db']) ? $GLOBALS['db'] : '', isset($GLOBALS['table']) ? $GLOBALS['table'] : '');
  1682.             echo "\n";
  1683.             ?>
  1684.     <tr>
  1685.         <td bgcolor="<?php echo $cfg['BgcolorOne']; ?>">
  1686.             <?php
  1687.             echo "\n";
  1688.             // Html format the query to be displayed
  1689.             // The nl2br function isn't used because its result isn't a valid
  1690.             // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")
  1691.             // If we want to show some sql code it is easiest to create it here
  1692.              /* SQL-Parser-Analyzer */
  1693.             $sqlnr = 1;
  1694.             if (!empty($GLOBALS['show_as_php'])) {
  1695.                 $new_line = '\'<br />' . "\n" . '        . \' ';
  1696.             }
  1697.             if (isset($new_line)) {
  1698.                  /* SQL-Parser-Analyzer */
  1699.                 $query_base = PMA_sqlAddslashes(htmlspecialchars($local_query));
  1700.                  /* SQL-Parser-Analyzer */
  1701.                 $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);
  1702.             } else {
  1703.                 $query_base = $local_query;
  1704.             }
  1705.  
  1706.             // Here we append the LIMIT added for navigation, to
  1707.             // enable its display. Adding it higher in the code
  1708.             // to $local_query would create a problem when
  1709.             // using the Refresh or Edit links.
  1710.  
  1711.             // Only append it on SELECTs.
  1712.  
  1713.             // FIXME: what would be the best to do when someone
  1714.             // hits Refresh: use the current LIMITs ?
  1715.  
  1716.             // TODO: use the parser instead of preg_match()
  1717.  
  1718.             if (preg_match('@^SELECT[[:space:]]+@i', $query_base)
  1719.              && isset($GLOBALS['sql_limit_to_append'])) {
  1720.                 $query_base .= $GLOBALS['sql_limit_to_append'];
  1721.             }
  1722.  
  1723.             if (!empty($GLOBALS['show_as_php'])) {
  1724.                 $query_base = '$sql  = \'' . $query_base;
  1725.             } else if (!empty($GLOBALS['validatequery'])) {
  1726.                 $query_base = PMA_validateSQL($query_base);
  1727.             } else {
  1728.                 // avoid reparsing query:
  1729.                 if (isset($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {
  1730.                     $parsed_sql = $GLOBALS['parsed_sql'];
  1731.                 } else {
  1732.                     $parsed_sql = PMA_SQP_parse($query_base);
  1733.                 }
  1734.                 $query_base = PMA_formatSql($parsed_sql, $query_base);
  1735.             }
  1736.  
  1737.             // Prepares links that may be displayed to edit/explain the query
  1738.             // (don't go to default pages, we must go to the page
  1739.             // where the query box is available)
  1740.             // (also, I don't see why we should check the goto variable)
  1741.  
  1742.             //if (!isset($GLOBALS['goto'])) {
  1743.                 //$edit_target = (isset($GLOBALS['table'])) ? $cfg['DefaultTabTable'] : $cfg['DefaultTabDatabase'];
  1744.             $edit_target = isset($GLOBALS['db']) ? (isset($GLOBALS['table']) ? 'tbl_properties.php' : 'db_details.php') : '';
  1745.             //} else if ($GLOBALS['goto'] != 'main.php') {
  1746.             //    $edit_target = $GLOBALS['goto'];
  1747.             //} else {
  1748.             //    $edit_target = '';
  1749.             //}
  1750.  
  1751.             if (isset($cfg['SQLQuery']['Edit'])
  1752.                 && ($cfg['SQLQuery']['Edit'] == TRUE )
  1753.                 && (!empty($edit_target))) {
  1754.  
  1755.                 $onclick = '';
  1756.                 if ($cfg['QueryFrameJS'] && $cfg['QueryFrame']) {
  1757.                     $onclick = 'onclick="focus_querywindow(\'' . urlencode($local_query) . '\'); return false;"';
  1758.                 }
  1759.  
  1760.                 $edit_link = ' [<a href="'
  1761.                            . $edit_target
  1762.                            . $url_qpart
  1763.                            . '&sql_query=' . urlencode($local_query) . '&show_query=1#querybox" ' . $onclick . '>' . $GLOBALS['strEdit'] . '</a>]';
  1764.             } else {
  1765.                 $edit_link = '';
  1766.             }
  1767.  
  1768.             // Want to have the query explained (Mike Beck 2002-05-22)
  1769.             // but only explain a SELECT (that has not been explained)
  1770.             /* SQL-Parser-Analyzer */
  1771.             if (isset($cfg['SQLQuery']['Explain'])
  1772.                 && $cfg['SQLQuery']['Explain'] == TRUE) {
  1773.  
  1774.                 // Detect if we are validating as well
  1775.                 // To preserve the validate uRL data
  1776.                 if (!empty($GLOBALS['validatequery'])) {
  1777.                     $explain_link_validate = '&validatequery=1';
  1778.                 } else {
  1779.                     $explain_link_validate = '';
  1780.                 }
  1781.  
  1782.                 $explain_link = ' [<a href="read_dump.php'
  1783.                               . $url_qpart
  1784.                               . $explain_link_validate
  1785.                               . '&sql_query=';
  1786.  
  1787.                 if (preg_match('@^SELECT[[:space:]]+@i', $local_query)) {
  1788.                     $explain_link .= urlencode('EXPLAIN ' . $local_query) . '">' . $GLOBALS['strExplain'];
  1789.                 } else if (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $local_query)) {
  1790.                     $explain_link .= urlencode(substr($local_query, 8)) . '">' . $GLOBALS['strNoExplain'];
  1791.                 } else {
  1792.                     $explain_link = '';
  1793.                 }
  1794.                 if (!empty($explain_link)) {
  1795.                     $explain_link .= '</a>]';
  1796.                 }
  1797.             } else {
  1798.                 $explain_link = '';
  1799.             } //show explain
  1800.  
  1801.             // Also we would like to get the SQL formed in some nice
  1802.             // php-code (Mike Beck 2002-05-22)
  1803.             if (isset($cfg['SQLQuery']['ShowAsPHP'])
  1804.                 && $cfg['SQLQuery']['ShowAsPHP'] == TRUE) {
  1805.                 $php_link = ' [<a href="read_dump.php'
  1806.                           . $url_qpart
  1807.                           . '&show_query=1'
  1808.                           . '&sql_query=' . urlencode($local_query)
  1809.                           . '&show_as_php=';
  1810.  
  1811.                 if (!empty($GLOBALS['show_as_php'])) {
  1812.                     $php_link .= '0">' . $GLOBALS['strNoPhp'];
  1813.                 } else {
  1814.                     $php_link .= '1">' . $GLOBALS['strPhp'];
  1815.                 }
  1816.                 $php_link .= '</a>]';
  1817.  
  1818.                 if (isset($GLOBALS['show_as_php']) && $GLOBALS['show_as_php'] == '1') {
  1819.                     $php_link .= ' [<a href="read_dump.php'
  1820.                               . $url_qpart
  1821.                               . '&show_query=1'
  1822.                               . '&sql_query=' . urlencode($local_query)
  1823.                               . '">' . $GLOBALS['strRunQuery'] . '</a>]';
  1824.                 }
  1825.  
  1826.             } else {
  1827.                 $php_link = '';
  1828.             } //show as php
  1829.  
  1830.             // Refresh query
  1831.             if (isset($cfg['SQLQuery']['Refresh'])
  1832.                 && $cfg['SQLQuery']['Refresh']
  1833.                 && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $local_query)) {
  1834.  
  1835.                 $refresh_link = ' [<a href="read_dump.php'
  1836.                           . $url_qpart
  1837.                           . '&show_query=1'
  1838.                           . '&sql_query=' . urlencode($local_query)
  1839.                           . '">';
  1840.                 $refresh_link .= $GLOBALS['strRefresh'];
  1841.                 $refresh_link .= '</a>]';
  1842.             } else {
  1843.                 $refresh_link = '';
  1844.             } //show as php
  1845.  
  1846.             if (isset($cfg['SQLValidator']['use'])
  1847.                 && $cfg['SQLValidator']['use'] == TRUE
  1848.                 && isset($cfg['SQLQuery']['Validate'])
  1849.                 && $cfg['SQLQuery']['Validate'] == TRUE) {
  1850.                 $validate_link = ' [<a href="read_dump.php'
  1851.                                . $url_qpart
  1852.                                . '&show_query=1'
  1853.                                . '&sql_query=' . urlencode($local_query)
  1854.                                . '&validatequery=';
  1855.                 if (!empty($GLOBALS['validatequery'])) {
  1856.                     $validate_link .= '0">' .  $GLOBALS['strNoValidateSQL'] ;
  1857.                 } else {
  1858.                     $validate_link .= '1">'. $GLOBALS['strValidateSQL'] ;
  1859.                 }
  1860.                 $validate_link .= '</a>]';
  1861.             } else {
  1862.                 $validate_link = '';
  1863.             } //validator
  1864.  
  1865.             // Displays the message
  1866.             echo '            <b>' . $GLOBALS['strSQLQuery'] . ':</b> ';
  1867.             echo '<br />' . "\n";
  1868.             echo '            ' . $query_base;
  1869.  
  1870.             unset($local_query);
  1871.             //Clean up the end of the PHP
  1872.             if (!empty($GLOBALS['show_as_php'])) {
  1873.                 echo '\';';
  1874.             }
  1875.             echo "\n";
  1876.             ?>
  1877.         </td>
  1878.     </tr>
  1879.     <?php
  1880.             if (!empty($edit_target)) {
  1881.                 echo '<tr><td bgcolor="' . $cfg['BgcolorOne'] . '" align="center">';
  1882.                 echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
  1883.                 echo '</td></tr>' . "\n";
  1884.             }
  1885.         }
  1886.         echo "\n";
  1887.         ?>
  1888.     </table>
  1889. </div><br />
  1890.         <?php
  1891.     } // end of the 'PMA_showMessage()' function
  1892.  
  1893.  
  1894.     /**
  1895.      * Formats $value to byte view
  1896.      *
  1897.      * @param    double   the value to format
  1898.      * @param    integer  the sensitiveness
  1899.      * @param    integer  the number of decimals to retain
  1900.      *
  1901.      * @return   array    the formatted value and its unit
  1902.      *
  1903.      * @access  public
  1904.      *
  1905.      * @author   staybyte
  1906.      * @version  1.2 - 18 July 2002
  1907.      */
  1908.     function PMA_formatByteDown($value, $limes = 6, $comma = 0)
  1909.     {
  1910.         $dh           = pow(10, $comma);
  1911.         $li           = pow(10, $limes);
  1912.         $return_value = $value;
  1913.         $unit         = $GLOBALS['byteUnits'][0];
  1914.  
  1915.         for ( $d = 6, $ex = 15; $d >= 1; $d--, $ex-=3 ) {
  1916.             if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * pow(10, $ex)) {
  1917.                 $value = round($value / ( pow(1024, $d) / $dh) ) /$dh;
  1918.                 $unit = $GLOBALS['byteUnits'][$d];
  1919.                 break 1;
  1920.             } // end if
  1921.         } // end for
  1922.  
  1923.         if ($unit != $GLOBALS['byteUnits'][0]) {
  1924.             $return_value = number_format($value, $comma, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
  1925.         } else {
  1926.             $return_value = number_format($value, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
  1927.         }
  1928.  
  1929.         return array($return_value, $unit);
  1930.     } // end of the 'PMA_formatByteDown' function
  1931.  
  1932.  
  1933.     /**
  1934.      * Extracts ENUM / SET options from a type definition string
  1935.      *
  1936.      * @param   string   The column type definition
  1937.      *
  1938.      * @return  array    The options or
  1939.      *          boolean  FALSE in case of an error.
  1940.      *
  1941.      * @author  rabus
  1942.      */
  1943.     function PMA_getEnumSetOptions($type_def) {
  1944.         $open = strpos($type_def, '(');
  1945.         $close = strrpos($type_def, ')');
  1946.         if (!$open || !$close) {
  1947.             return FALSE;
  1948.         }
  1949.         $options = substr($type_def, $open + 2, $close - $open - 3);
  1950.         $options = explode('\',\'', $options);
  1951.         return $options;
  1952.     } // end of the 'PMA_getEnumSetOptions' function
  1953.  
  1954.     /**
  1955.      * Writes localised date
  1956.      *
  1957.      * @param   string   the current timestamp
  1958.      *
  1959.      * @return  string   the formatted date
  1960.      *
  1961.      * @access  public
  1962.      */
  1963.     function PMA_localisedDate($timestamp = -1, $format = '')
  1964.     {
  1965.         global $datefmt, $month, $day_of_week;
  1966.  
  1967.         if ($format == '') {
  1968.             $format = $datefmt;
  1969.         }
  1970.  
  1971.         if ($timestamp == -1) {
  1972.             $timestamp = time();
  1973.         }
  1974.  
  1975.         $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
  1976.         $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
  1977.  
  1978.         return strftime($date, $timestamp);
  1979.     } // end of the 'PMA_localisedDate()' function
  1980.  
  1981.  
  1982.     /**
  1983.      * Prints out a tab for tabbed navigation.
  1984.      * If the variables $link and $args ar left empty, an inactive tab is created
  1985.      *
  1986.      * @param   string  the text to be displayed as link
  1987.      * @param   string  main link file, e.g. "test.php"
  1988.      * @param   string  link arguments
  1989.      * @param   string  link attributes
  1990.      * @param   string  include '?' even though no attributes are set. Can be set empty, should be '?'.
  1991.      * @param   boolean force display TAB as active
  1992.      *
  1993.      * @return  string  two table cells, the first beeing a separator, the second the tab itself
  1994.      *
  1995.      * @access  public
  1996.      */
  1997. /* replaced with a newer function
  1998.    2004-05-20 by Michael Keck <mail_at_michaelkeck_dot_de>
  1999. */
  2000. /*
  2001.     function PMA_printTab($text, $link, $args = '', $attr = '', $class = '', $sep = '?', $active = false) {
  2002.         global $PHP_SELF, $cfg;
  2003.         global $db_details_links_count_tabs;
  2004.  
  2005.         if (!empty($class)) {
  2006.             $class = ' class="' . $class . '"';
  2007.             $addclass = ' ' . $class;
  2008.         } else {
  2009.             $addclass = '';
  2010.         }
  2011.  
  2012.         if (((!isset($GLOBALS['active_page']) && basename($PHP_SELF) == $link) ||
  2013.                 $active ||
  2014.                 (isset($GLOBALS['active_page']) && $GLOBALS['active_page'] == $link)
  2015.             ) && ($text != $GLOBALS['strEmpty'] && $text != $GLOBALS['strDrop'])) {
  2016.             $addclass .= ' activetab';
  2017.         }
  2018.  
  2019.         $db_details_links_count_tabs++;
  2020.  
  2021.         if ($cfg['LightTabs']) {
  2022.             $out = '';
  2023.             if (strlen($link) > 0) {
  2024.                 $out .= '<a class="tab" href="' . $link . $sep . $args . '"' . $attr . $class . '>'
  2025.                      .  '' . $text . '</a>';
  2026.             } else {
  2027.                 $out .= '<span class="tab">' . $text . '</span>';
  2028.             }
  2029.             $out = '[ ' . $out . ' ]   ';
  2030.         } else {
  2031.             $out     = "\n" . '        '
  2032.                      . '<td class="tab nowrap' . $addclass . '">'
  2033.                      . "\n" . '            ';
  2034.             if (strlen($link) > 0) {
  2035.                 $out .= '<a href="' . $link . $sep . $args . '"' . $attr .  $class . '>'
  2036.                      .  $text . '</a>';
  2037.             } else {
  2038.                 $out .= $text;
  2039.             }
  2040.             $out     .= "\n" . '        '
  2041.                      .  '</td>'
  2042.                      .  "\n" . '        '
  2043.                      .  '<td width="8"> </td>';
  2044.         }
  2045.  
  2046.         return $out;
  2047.     } // end of the 'PMA_printTab()' function
  2048. */
  2049. // the new one:
  2050.     function PMA_printTab($text, $link, $args = '', $attr = '', $class = '', $sep = '?', $active = false) {
  2051.         global $PHP_SELF, $cfg;
  2052.         global $db_details_links_count_tabs;
  2053.         $addclass = '';
  2054.         if (((!isset($GLOBALS['active_page']) && basename($PHP_SELF) == $link) ||
  2055.                 $active ||
  2056.                 (isset($GLOBALS['active_page']) && $GLOBALS['active_page'] == $link)
  2057.             ) && ($text != $GLOBALS['strEmpty'] && $text != $GLOBALS['strDrop'])) {
  2058.             $addclass = 'Active';
  2059.         }
  2060.         if ($text == $GLOBALS['strEmpty'] && $text == $GLOBALS['strDrop']) $addclass = 'Drop';
  2061.         if (empty($class)){
  2062.             if (empty($addclass)) { $addclass = 'Normal'; }
  2063.         } else { $addclass = $class; }
  2064.  
  2065.         $db_details_links_count_tabs++;
  2066.  
  2067.         if ($cfg['LightTabs']) {
  2068.             $out = '';
  2069.             if (!empty($link)) {
  2070.                 $out .= '<a class="tab" href="' . $link . $sep . $args . '"' . $attr . $class . '>'
  2071.                      .  '' . $text . '</a>';
  2072.             } else {
  2073.                 $out .= '<span class="tab">' . $text . '</span>';
  2074.             }
  2075.             $out = '[ ' . $out . ' ]   ';
  2076.         } else {
  2077.             $out     = "\n" . '        '
  2078.                      . '<td class="nav' . $addclass . '" nowrap="nowrap">'
  2079.                      . "\n" . '            ';
  2080.             if (!empty($link)) {
  2081.                 $out .= '<a href="' . $link . $sep . $args . '"' . $attr . '>'
  2082.                      .  $text . '</a>';
  2083.             } else {
  2084.                 $out .= $text;
  2085.             }
  2086.             $out     .= "\n" . '        '
  2087.                      .  '</td>'
  2088.                      .  "\n" . '        '
  2089.                      .  '<td class="navSpacer"><img src="' . $GLOBALS['pmaThemeImage'] . 'spacer.png' . '" width="1" height="1" border="0" alt="" /></td>';
  2090.         }
  2091.  
  2092.         return $out;
  2093.     } // end of the 'PMA_printTab()' function
  2094.  
  2095.  
  2096.     /**
  2097.      * Displays a link, or a button if the link's URL is too large, to
  2098.      * accommodate some browsers' limitations
  2099.      *
  2100.      * @param  string  the URL
  2101.      * @param  string  the link message
  2102.      * @param  string  js confirmation
  2103.      * @param  boolean we set this to FALSE when we are already in a form,
  2104.      *                 to avoid generating nested forms
  2105.      *
  2106.      * @return string  the results to be echoed or saved in an array
  2107.      */
  2108.     function PMA_linkOrButton($url, $message, $js_conf, $allow_button = TRUE)
  2109.     {
  2110.         // previously the limit was set to 2047, it seems 1000 is better
  2111.         if (strlen($url) <= 1000) {
  2112.             $onclick_url        = (empty($js_conf) ? '' : ' onclick="return confirmLink(this, \'' . $js_conf . '\')"');
  2113.             $link_or_button     = '        <a href="' . $url . '"' . $onclick_url . '>' . "\n"
  2114.                                 . '           ' . $message . '</a>' . "\n";
  2115.         }
  2116.         elseif ($allow_button) {
  2117.             $edit_url_parts     = parse_url($url);
  2118.             $query_parts        = explode('&', $edit_url_parts['query']);
  2119.             $link_or_button     = '        <form action="'
  2120.                                 . $edit_url_parts['path']
  2121.                                 . '" method="post">' . "\n";
  2122.             foreach ($query_parts AS $query_pair) {
  2123.                 list($eachvar, $eachval) = explode('=', $query_pair);
  2124.                 $link_or_button .= '            <input type="hidden" name="' . str_replace('amp;', '', $eachvar) . '" value="' . htmlspecialchars(urldecode($eachval)) . '" />' . "\n";
  2125.             } // end while
  2126.  
  2127.             if (stristr($message, '<img')) {
  2128.                 $link_or_button     .= '            <input type="image" src="' . preg_replace('@^.*src="(.*)".*$@si', '\1', $message) . '" value="'
  2129.                                     . htmlspecialchars(preg_replace('@^.*alt="(.*)".*$@si', '\1', $message)) . '" />' . "\n" . '</form>' . "\n";
  2130.             } else {
  2131.                 $link_or_button     .= '            <input type="submit" value="'
  2132.                                     . htmlspecialchars($message) . '" />' . "\n" . '</form>' . "\n";
  2133.             }
  2134.         } else {
  2135.             $link_or_button = ' <dfn title="' . $GLOBALS['strNeedPrimaryKey'] . '">?</dfn> ';
  2136.         } // end if... else...
  2137.  
  2138.             return $link_or_button;
  2139.     } // end of the 'PMA_linkOrButton()' function
  2140.  
  2141.  
  2142.     /**
  2143.      * Returns a given timespan value in a readable format.
  2144.      *
  2145.      * @param  int     the timespan
  2146.      *
  2147.      * @return string  the formatted value
  2148.      */
  2149.     function PMA_timespanFormat($seconds)
  2150.     {
  2151.         $return_string = '';
  2152.         $days = floor($seconds / 86400);
  2153.         if ($days > 0) {
  2154.             $seconds -= $days * 86400;
  2155.         }
  2156.         $hours = floor($seconds / 3600);
  2157.         if ($days > 0 || $hours > 0) {
  2158.             $seconds -= $hours * 3600;
  2159.         }
  2160.         $minutes = floor($seconds / 60);
  2161.         if ($days > 0 || $hours > 0 || $minutes > 0) {
  2162.             $seconds -= $minutes * 60;
  2163.         }
  2164.         return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);
  2165.     }
  2166.  
  2167.     /**
  2168.      * Takes a string and outputs each character on a line for itself. Used mainly for horizontalflipped display mode.
  2169.      * Takes care of special html-characters.
  2170.      * Fulfills todo-item http://sourceforge.net/tracker/index.php?func=detail&aid=544361&group_id=23067&atid=377411
  2171.      *
  2172.      * @param   string   The string
  2173.      * @param   string   The Separator (defaults to "<br />\n")
  2174.      *
  2175.      * @access  public
  2176.      * @author  Garvin Hicking <me@supergarv.de>
  2177.      * @return  string      The flipped string
  2178.      */
  2179.     function PMA_flipstring($string, $Separator = "<br />\n") {
  2180.         $format_string = '';
  2181.         $charbuff = false;
  2182.  
  2183.         for ($i = 0; $i < strlen($string); $i++) {
  2184.             $char = $string{$i};
  2185.             $append = false;
  2186.  
  2187.             if ($char == '&') {
  2188.                 $format_string .= $charbuff;
  2189.                 $charbuff = $char;
  2190.                 $append = true;
  2191.             } elseif (!empty($charbuff)) {
  2192.                 $charbuff .= $char;
  2193.             } elseif ($char == ';' && !empty($charbuff)) {
  2194.                 $format_string .= $charbuff;
  2195.                 $charbuff = false;
  2196.                 $append = true;
  2197.             } else {
  2198.                 $format_string .= $char;
  2199.                 $append = true;
  2200.             }
  2201.  
  2202.             if ($append && ($i != strlen($string))) {
  2203.                 $format_string .= $Separator;
  2204.             }
  2205.         }
  2206.  
  2207.         return $format_string;
  2208.     }
  2209.  
  2210.  
  2211.     /**
  2212.      * Function added to avoid path disclosures.
  2213.      * Called by each script that needs parameters, it displays
  2214.      * an error message and, by defaults, stops the execution.
  2215.      *
  2216.      * @param   array   The names of the parameters needed by the calling
  2217.      *                  script.
  2218.      * @param   boolean Stop the execution?
  2219.      *                  (Set this manually to FALSE in the calling script
  2220.      *                   until you know all needed parameters to check).
  2221.      *
  2222.      * @access  public
  2223.      * @author  Marc Delisle (lem9@users.sourceforge.net)
  2224.      */
  2225.     function PMA_checkParameters($params, $die = TRUE) {
  2226.         global $PHP_SELF;
  2227.  
  2228.         $reported_script_name = basename($PHP_SELF);
  2229.         $found_error = FALSE;
  2230.         $error_message = '';
  2231.  
  2232.         foreach ($params AS $param) {
  2233.             if (!isset($GLOBALS[$param])) {
  2234.                 $error_message .= $reported_script_name . ': Missing parameter: ' . $param . '<br />';
  2235.                 $found_error = TRUE;
  2236.             }
  2237.         }
  2238.         if ($found_error) {
  2239.             require_once('./libraries/header_meta_style.inc.php');
  2240.             echo '</head><body><p>' . $error_message . '</p></body></html>';
  2241.             if ($die) {
  2242.                 exit();
  2243.             }
  2244.         }
  2245.     } // end function
  2246.  
  2247.     // Kanji encoding convert feature appended by Y.Kawada (2002/2/20)
  2248.     if (@function_exists('mb_convert_encoding')
  2249.         && strpos(' ' . $lang, 'ja-')
  2250.         && file_exists('./libraries/kanji-encoding.lib.php')) {
  2251.         require_once('./libraries/kanji-encoding.lib.php');
  2252.         define('PMA_MULTIBYTE_ENCODING', 1);
  2253.     } // end if
  2254.  
  2255.     /**
  2256.      * Function to check valid extension of file. It accepts entered
  2257.      * extensions and bz2 and gz if supported.
  2258.      *
  2259.      * @param   string  File name to be tested.
  2260.      * @param   string  Extension that is valid.
  2261.      *
  2262.      * @access  public
  2263.      * @author  Michal Cihar (nijel@users.sourceforge.net)
  2264.      * @return  bool    Whether extension is valid
  2265.      */
  2266.     function PMA_checkFileExtensions($file, $extension) {
  2267.         if (substr($file, -1 * strlen($extension)) == $extension) {
  2268.             return TRUE;
  2269.         }
  2270.         if ($GLOBALS['cfg']['GZipDump'] && @function_exists('gzopen')) {
  2271.             if (substr($file, -3 - strlen($extension)) == $extension . '.gz') {
  2272.                 return TRUE;
  2273.             }
  2274.         }
  2275.         if ($GLOBALS['cfg']['BZipDump'] && @function_exists('bzdecompress')) {
  2276.             if (substr($file, -4 - strlen($extension)) == $extension . '.bz2') {
  2277.                 return TRUE;
  2278.             }
  2279.         }
  2280.         return FALSE;
  2281.     } // end function
  2282.  
  2283.     /**
  2284.      * Function to generate unique condition for specified row.
  2285.      *
  2286.      * @param   resource    handle for current query
  2287.      * @param   integer     number of fields
  2288.      * @param   array       meta information about fields
  2289.      * @param   array       current row
  2290.      *
  2291.      * @access  public
  2292.      * @author  Michal Cihar (michal@cihar.com)
  2293.      * @return  string      calculated condition
  2294.      */
  2295.     function PMA_getUvaCondition($handle, $fields_cnt, $fields_meta, $row) {
  2296.  
  2297.         $primary_key              = '';
  2298.         $unique_key               = '';
  2299.         $uva_nonprimary_condition = '';
  2300.  
  2301.         for ($i = 0; $i < $fields_cnt; ++$i) {
  2302.             $field_flags = PMA_DBI_field_flags($handle, $i);
  2303.             $meta      = $fields_meta[$i];
  2304.             // do not use an alias in a condition
  2305.             $column_for_condition = $meta->name;
  2306.             if (isset($analyzed_sql[0]['select_expr']) && is_array($analyzed_sql[0]['select_expr'])) {
  2307.                 foreach ($analyzed_sql[0]['select_expr'] AS $select_expr_position => $select_expr) {
  2308.                     $alias = $analyzed_sql[0]['select_expr'][$select_expr_position]['alias'];
  2309.                     if (!empty($alias)) {
  2310.                         $true_column = $analyzed_sql[0]['select_expr'][$select_expr_position]['column'];
  2311.                         if ($alias == $meta->name) {
  2312.                             $column_for_condition = $true_column;
  2313.                         } // end if
  2314.                     } // end if
  2315.                 } // end while
  2316.             }
  2317.  
  2318.             // to fix the bug where float fields (primary or not)
  2319.             // can't be matched because of the imprecision of
  2320.             // floating comparison, use CONCAT
  2321.             // (also, the syntax "CONCAT(field) IS NULL"
  2322.             // that we need on the next "if" will work)
  2323.             if ($meta->type == 'real') {
  2324.                 $condition = ' CONCAT(' . PMA_backquote($column_for_condition) . ') ';
  2325.             } else {
  2326.                 // string and blob fields have to be converted using
  2327.                 // the system character set (always utf8) since
  2328.                 // mysql4.1 can use different charset for fields.
  2329.                 if (PMA_MYSQL_INT_VERSION >= 40100 && ($meta->type == 'string' || $meta->type == 'blob')) {
  2330.                     $condition = ' CONVERT(' . PMA_backquote($column_for_condition) . ' USING utf8) ';
  2331.                 } else {
  2332.                     $condition = ' ' . PMA_backquote($column_for_condition) . ' ';
  2333.                 }
  2334.             } // end if... else...
  2335.  
  2336.             if (!isset($row[$i]) || is_null($row[$i])) {
  2337.                 $condition .= 'IS NULL AND';
  2338.             } else {
  2339.                 // timestamp is numeric on some MySQL 4.1
  2340.                 if ($meta->numeric && $meta->type != 'timestamp') {
  2341.                     $condition .= '= ' . $row[$i] . ' AND';
  2342.                 } elseif ($meta->type == 'blob'
  2343.                     // hexify only if this is a true not empty BLOB
  2344.                      && stristr($field_flags, 'BINARY')
  2345.                      && !empty($row[$i])) {
  2346.                         // use a CAST if possible, to avoid problems
  2347.                         // if the field contains wildcard characters % or _
  2348.                         if (PMA_MYSQL_INT_VERSION < 40002) {
  2349.                             $condition .= 'LIKE 0x' . bin2hex($row[$i]). ' AND';
  2350.                         } else {
  2351.                             $condition .= '= CAST(0x' . bin2hex($row[$i]). ' AS BINARY) AND';
  2352.                         }
  2353.                 } else {
  2354.                     $condition .= '= \'' . PMA_sqlAddslashes($row[$i], FALSE, TRUE) . '\' AND';
  2355.                 }
  2356.             }
  2357.             if ($meta->primary_key > 0) {
  2358.                 $primary_key .= $condition;
  2359.             } else if ($meta->unique_key > 0) {
  2360.                 $unique_key  .= $condition;
  2361.             }
  2362.             $uva_nonprimary_condition .= $condition;
  2363.         } // end for
  2364.  
  2365.         // Correction uva 19991216: prefer primary or unique keys
  2366.         // for condition, but use conjunction of all values if no
  2367.         // primary key
  2368.         if ($primary_key) {
  2369.             $uva_condition = $primary_key;
  2370.         } else if ($unique_key) {
  2371.             $uva_condition = $unique_key;
  2372.         } else {
  2373.             $uva_condition = $uva_nonprimary_condition;
  2374.         }
  2375.  
  2376.         return preg_replace('|\s?AND$|', '', $uva_condition);
  2377.     } // end function
  2378.  
  2379.     /**
  2380.      * Function to generate unique condition for specified row.
  2381.      *
  2382.      * @param   string      name of button element
  2383.      * @param   string      class of button element
  2384.      * @param   string      name of image element
  2385.      * @param   string      text to display
  2386.      * @param   string      image to display
  2387.      *
  2388.      * @access  public
  2389.      * @author  Michal Cihar (michal@cihar.com)
  2390.      */
  2391.     function PMA_buttonOrImage($button_name, $button_class, $image_name, $text, $image) {
  2392.         global $pmaThemeImage, $propicon;
  2393.  
  2394.         /* Opera has trouble with <input type="image"> */
  2395.         /* IE has trouble with <button> */
  2396.         if (PMA_USR_BROWSER_AGENT != 'IE') {
  2397.             echo '<button class="' . $button_class . '" type="submit" name="' . $button_name . '" value="' . $text . '" title="' . $text . '">' . "\n"
  2398.                . '<img src="' . $pmaThemeImage . $image . '" title="' . $text . '" alt="' . $text . '" width="16" height="16" />' . (($propicon == 'both') ? ' ' . $text : '') . "\n"
  2399.                . '</button>' . "\n";
  2400.         } else {
  2401.             echo '<input type="image" name="' . $image_name . '" value="' .$text . '" title="' . $text . '" src="' . $pmaThemeImage . $image . '" />'  . (($propicon == 'both') ? ' ' . $text : '') . "\n";
  2402.         }
  2403.     } // end function
  2404.  
  2405.     /**
  2406.      * Generate a pagination selector for browsing resultsets
  2407.      *
  2408.      * @param   string      URL for the JavaScript
  2409.      * @param   string      Number of rows in the pagination set
  2410.      * @param   string      current page number
  2411.      * @param   string      number of total pages
  2412.      * @param   string      If the number of pages is lower than this
  2413.      *                      variable, no pages will be ommitted in
  2414.      *                      pagination
  2415.      * @param   string      How many rows at the beginning should always
  2416.      *                      be shown?
  2417.      * @param   string      How many rows at the end should always
  2418.      *                      be shown?
  2419.      * @param   string      Percentage of calculation page offsets to
  2420.      *                      hop to a next page
  2421.      * @param   string      Near the current page, how many pages should
  2422.      *                      be considered "nearby" and displayed as
  2423.      *                      well?
  2424.      *
  2425.      * @access  public
  2426.      * @author  Garvin Hicking (pma@supergarv.de)
  2427.      */
  2428.     function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1, $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20, $range = 10) {
  2429.         $gotopage = '<br />' . $GLOBALS['strPageNumber']
  2430.                   . '<select name="goToPage" onchange="goToUrl(this, \'' . $url . '\');">' . "\n";
  2431.         if ($nbTotalPage < $showAll) {
  2432.             $pages = range(1, $nbTotalPage);
  2433.         } else {
  2434.             $pages = array();
  2435.  
  2436.             // Always show first X pages
  2437.             for ($i = 1; $i <= $sliceStart; $i++) {
  2438.                 $pages[] = $i;
  2439.             }
  2440.  
  2441.             // Always show last X pages
  2442.             for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
  2443.                 $pages[] = $i;
  2444.             }
  2445.  
  2446.             // garvin: Based on the number of results we add the specified $percent percentate to each page number,
  2447.             // so that we have a representing page number every now and then to immideately jump to specific pages.
  2448.             // As soon as we get near our currently chosen page ($pageNow - $range), every page number will be
  2449.             // shown.
  2450.             $i = $sliceStart;
  2451.             $x = $nbTotalPage - $sliceEnd;
  2452.             $met_boundary = false;
  2453.             while($i <= $x) {
  2454.                 if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {
  2455.                     // If our pageselector comes near the current page, we use 1 counter increments
  2456.                     $i++;
  2457.                     $met_boundary = true;
  2458.                 } else {
  2459.                     // We add the percentate increment to our current page to hop to the next one in range
  2460.                     $i = $i + floor($nbTotalPage / $percent);
  2461.  
  2462.                     // Make sure that we do not cross our boundaries.
  2463.                     if ($i > ($pageNow - $range) && !$met_boundary) {
  2464.                         $i = $pageNow - $range;
  2465.                     }
  2466.                 }
  2467.  
  2468.                 if ($i > 0 && $i <= $x) {
  2469.                     $pages[] = $i;
  2470.                 }
  2471.             }
  2472.  
  2473.             // Since because of ellipsing of the current page some numbers may be double,
  2474.             // we unify our array:
  2475.             sort($pages);
  2476.             $pages = array_unique($pages);
  2477.         }
  2478.  
  2479.         foreach($pages AS $i) {
  2480.             if ($i == $pageNow) {
  2481.                 $selected = 'selected="selected" style="font-weight: bold"';
  2482.             } else {
  2483.                 $selected = '';
  2484.             }
  2485.             $gotopage .= '                <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
  2486.         }
  2487.  
  2488.         $gotopage .= ' </select>';
  2489.  
  2490.         return $gotopage;
  2491.     }
  2492.  
  2493. } // end if: minimal common.lib needed?
  2494.  
  2495. ?>
  2496.